Real-World Projects

Employee Payroll Management System

A comprehensive payroll system that calculates salaries, handles deductions, manages employee records, tracks attendance, generates payslips, and computes tax withholdings.

Problem Description

Create a payroll management system that:

  • Manages employee records (permanent, contract, hourly)
  • Calculates gross and net salary
  • Handles deductions (tax, insurance, provident fund)
  • Tracks attendance and leave
  • Generates detailed payslips
  • Supports different employee types with different pay structures

Code

PayrollSystem.java
import java.util.*;
import java.time.*;

enum EmployeeType {
    PERMANENT, CONTRACT, HOURLY
}

class Employee {
    protected String employeeId;
    protected String name;
    protected String department;
    protected EmployeeType type;
    protected double basicSalary;
    
    public Employee(String employeeId, String name, String department,
                   EmployeeType type, double basicSalary) {
        this.employeeId = employeeId;
        this.name = name;
        this.department = department;
        this.type = type;
        this.basicSalary = basicSalary;
    }
    
    public String getEmployeeId() { return employeeId; }
    public String getName() { return name; }
    public String getDepartment() { return department; }
    public EmployeeType getType() { return type; }
    public double getBasicSalary() { return basicSalary; }
    
    public double calculateGrossSalary() {
        return basicSalary;
    }
}

class PermanentEmployee extends Employee {
    private double hra; // House Rent Allowance
    private double da;  // Dearness Allowance
    private double ta;  // Transport Allowance
    
    public PermanentEmployee(String employeeId, String name, String department,
                           double basicSalary) {
        super(employeeId, name, department, EmployeeType.PERMANENT, basicSalary);
        this.hra = basicSalary * 0.20; // 20% of basic
        this.da = basicSalary * 0.15;  // 15% of basic
        this.ta = 2000;                 // Fixed
    }
    
    @Override
    public double calculateGrossSalary() {
        return basicSalary + hra + da + ta;
    }
    
    public double getHRA() { return hra; }
    public double getDA() { return da; }
    public double getTA() { return ta; }
}

class ContractEmployee extends Employee {
    private int contractMonths;
    private LocalDate contractEndDate;
    
    public ContractEmployee(String employeeId, String name, String department,
                          double monthlySalary, int contractMonths) {
        super(employeeId, name, department, EmployeeType.CONTRACT, monthlySalary);
        this.contractMonths = contractMonths;
        this.contractEndDate = LocalDate.now().plusMonths(contractMonths);
    }
    
    public LocalDate getContractEndDate() {
        return contractEndDate;
    }
}

class HourlyEmployee extends Employee {
    private double hourlyRate;
    private int hoursWorked;
    
    public HourlyEmployee(String employeeId, String name, String department,
                        double hourlyRate) {
        super(employeeId, name, department, EmployeeType.HOURLY, 0);
        this.hourlyRate = hourlyRate;
        this.hoursWorked = 0;
    }
    
    public void setHoursWorked(int hours) {
        this.hoursWorked = hours;
    }
    
    @Override
    public double calculateGrossSalary() {
        double regularPay = Math.min(hoursWorked, 160) * hourlyRate;
        double overtimePay = Math.max(0, hoursWorked - 160) * hourlyRate * 1.5;
        return regularPay + overtimePay;
    }
    
    public double getHourlyRate() { return hourlyRate; }
    public int getHoursWorked() { return hoursWorked; }
}

class Deductions {
    private double providentFund;
    private double incomeTax;
    private double professionalTax;
    private double insurance;
    
    public Deductions(double grossSalary) {
        calculateDeductions(grossSalary);
    }
    
    private void calculateDeductions(double grossSalary) {
        // PF: 12% of basic (assuming basic is 50% of gross for calculation)
        this.providentFund = (grossSalary * 0.5) * 0.12;
        
        // Income tax (simplified progressive tax)
        if (grossSalary <= 25000) {
            this.incomeTax = 0;
        } else if (grossSalary <= 50000) {
            this.incomeTax = (grossSalary - 25000) * 0.05;
        } else if (grossSalary <= 100000) {
            this.incomeTax = 1250 + (grossSalary - 50000) * 0.10;
        } else {
            this.incomeTax = 6250 + (grossSalary - 100000) * 0.20;
        }
        
        // Professional tax
        this.professionalTax = 200;
        
        // Insurance
        this.insurance = 500;
    }
    
    public double getTotalDeductions() {
        return providentFund + incomeTax + professionalTax + insurance;
    }
    
    public double getProvidentFund() { return providentFund; }
    public double getIncomeTax() { return incomeTax; }
    public double getProfessionalTax() { return professionalTax; }
    public double getInsurance() { return insurance; }
}

class Payslip {
    private Employee employee;
    private YearMonth payPeriod;
    private double grossSalary;
    private Deductions deductions;
    private double netSalary;
    
    public Payslip(Employee employee, YearMonth payPeriod) {
        this.employee = employee;
        this.payPeriod = payPeriod;
        this.grossSalary = employee.calculateGrossSalary();
        this.deductions = new Deductions(grossSalary);
        this.netSalary = grossSalary - deductions.getTotalDeductions();
    }
    
    public void generatePayslip() {
        System.out.println("\n╔═══════════════════════════════════════════════════════════════╗");
        System.out.println("║                        PAYSLIP                                ║");
        System.out.println("╠═══════════════════════════════════════════════════════════════╣");
        System.out.println("║ Employee ID   : " + employee.getEmployeeId());
        System.out.println("║ Name          : " + employee.getName());
        System.out.println("║ Department    : " + employee.getDepartment());
        System.out.println("║ Type          : " + employee.getType());
        System.out.println("║ Pay Period    : " + payPeriod);
        System.out.println("║ Pay Date      : " + LocalDate.now());
        System.out.println("╠═══════════════════════════════════════════════════════════════╣");
        
        System.out.println("║                    EARNINGS                                   ║");
        System.out.println("╠═══════════════════════════════════════════════════════════════╣");
        
        if (employee instanceof PermanentEmployee) {
            PermanentEmployee perm = (PermanentEmployee) employee;
            System.out.printf("║ Basic Salary           : ₹%10.2f                      ║\n", perm.getBasicSalary());
            System.out.printf("║ HRA (20%%)              : ₹%10.2f                      ║\n", perm.getHRA());
            System.out.printf("║ DA (15%%)               : ₹%10.2f                      ║\n", perm.getDA());
            System.out.printf("║ TA                     : ₹%10.2f                      ║\n", perm.getTA());
        } else if (employee instanceof HourlyEmployee) {
            HourlyEmployee hourly = (HourlyEmployee) employee;
            System.out.printf("║ Hourly Rate            : ₹%10.2f                      ║\n", hourly.getHourlyRate());
            System.out.printf("║ Hours Worked           : %d hours                         ║\n", hourly.getHoursWorked());
        } else {
            System.out.printf("║ Monthly Salary         : ₹%10.2f                      ║\n", employee.getBasicSalary());
        }
        
        System.out.println("╠═══════════════════════════════════════════════════════════════╣");
        System.out.printf("║ GROSS SALARY           : ₹%10.2f                      ║\n", grossSalary);
        System.out.println("╠═══════════════════════════════════════════════════════════════╣");
        
        System.out.println("║                    DEDUCTIONS                                 ║");
        System.out.println("╠═══════════════════════════════════════════════════════════════╣");
        System.out.printf("║ Provident Fund (12%%)   : ₹%10.2f                      ║\n", deductions.getProvidentFund());
        System.out.printf("║ Income Tax             : ₹%10.2f                      ║\n", deductions.getIncomeTax());
        System.out.printf("║ Professional Tax       : ₹%10.2f                      ║\n", deductions.getProfessionalTax());
        System.out.printf("║ Insurance              : ₹%10.2f                      ║\n", deductions.getInsurance());
        System.out.println("╠═══════════════════════════════════════════════════════════════╣");
        System.out.printf("║ TOTAL DEDUCTIONS       : ₹%10.2f                      ║\n", deductions.getTotalDeductions());
        System.out.println("╠═══════════════════════════════════════════════════════════════╣");
        System.out.printf("║ NET SALARY             : ₹%10.2f                      ║\n", netSalary);
        System.out.println("╚═══════════════════════════════════════════════════════════════╝");
        
        System.out.println("\nAmount in words: " + convertToWords((int)netSalary) + " Rupees Only");
        System.out.println("\nThis is a computer-generated payslip and does not require signature.");
    }
    
    private String convertToWords(int number) {
        if (number == 0) return "Zero";
        
        String[] ones = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
        String[] tens = {"", "", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
        String[] teens = {"Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
        
        if (number < 10) return ones[number];
        if (number < 20) return teens[number - 10];
        if (number < 100) return tens[number / 10] + " " + ones[number % 10];
        if (number < 1000) return ones[number / 100] + " Hundred " + convertToWords(number % 100);
        if (number < 100000) return convertToWords(number / 1000) + " Thousand " + convertToWords(number % 1000);
        return convertToWords(number / 100000) + " Lakh " + convertToWords(number % 100000);
    }
    
    public double getNetSalary() {
        return netSalary;
    }
}

class PayrollSystem {
    private HashMap<String, Employee> employees;
    private ArrayList<Payslip> payslipHistory;
    
    public PayrollSystem() {
        employees = new HashMap<>();
        payslipHistory = new ArrayList<>();
    }
    
    public void addEmployee(Employee employee) {
        employees.put(employee.getEmployeeId(), employee);
        System.out.println("✓ Employee added: " + employee.getName());
    }
    
    public void generatePayslip(String employeeId, YearMonth payPeriod) {
        Employee employee = employees.get(employeeId);
        if (employee == null) {
            System.out.println("✗ Employee not found!");
            return;
        }
        
        Payslip payslip = new Payslip(employee, payPeriod);
        payslip.generatePayslip();
        payslipHistory.add(payslip);
    }
    
    public void displayAllEmployees() {
        System.out.println("\n╔═══════════════════════════════════════════════════════════════╗");
        System.out.println("║                    EMPLOYEE DIRECTORY                         ║");
        System.out.println("╚═══════════════════════════════════════════════════════════════╝");
        
        System.out.printf("\n%-12s %-20s %-15s %-10s %-12s\n",
            "EMP ID", "Name", "Department", "Type", "Salary");
        System.out.println("─".repeat(75));
        
        for (Employee emp : employees.values()) {
            System.out.printf("%-12s %-20s %-15s %-10s ₹%-12.2f\n",
                emp.getEmployeeId(), emp.getName(), emp.getDepartment(),
                emp.getType(), emp.calculateGrossSalary());
        }
    }
}

public class EmployeePayrollSystem {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        PayrollSystem payroll = new PayrollSystem();
        
        System.out.println("╔═══════════════════════════════════════════════╗");
        System.out.println("║     EMPLOYEE PAYROLL MANAGEMENT SYSTEM        ║");
        System.out.println("╚═══════════════════════════════════════════════╝\n");
        
        // Sample employees
        payroll.addEmployee(new PermanentEmployee("EMP001", "John Doe", "IT", 50000));
        payroll.addEmployee(new ContractEmployee("EMP002", "Jane Smith", "Marketing", 40000, 12));
        HourlyEmployee hourly = new HourlyEmployee("EMP003", "Bob Wilson", "Support", 500);
        hourly.setHoursWorked(180); // 180 hours in a month
        payroll.addEmployee(hourly);
        
        boolean running = true;
        
        while (running) {
            System.out.println("\n" + "═".repeat(50));
            System.out.println("              PAYROLL MENU");
            System.out.println("═".repeat(50));
            System.out.println("  1. Add Permanent Employee");
            System.out.println("  2. Add Contract Employee");
            System.out.println("  3. Add Hourly Employee");
            System.out.println("  4. Display All Employees");
            System.out.println("  5. Generate Payslip");
            System.out.println("  6. Set Hours for Hourly Employee");
            System.out.println("  0. Exit");
            System.out.println("═".repeat(50));
            System.out.print("Enter choice: ");
            
            int choice = scanner.nextInt();
            scanner.nextLine();
            
            switch (choice) {
                case 1:
                    System.out.print("\nEmployee ID: ");
                    String id1 = scanner.nextLine();
                    System.out.print("Name: ");
                    String name1 = scanner.nextLine();
                    System.out.print("Department: ");
                    String dept1 = scanner.nextLine();
                    System.out.print("Basic Salary: ₹");
                    double salary1 = scanner.nextDouble();
                    payroll.addEmployee(new PermanentEmployee(id1, name1, dept1, salary1));
                    break;
                    
                case 2:
                    System.out.print("\nEmployee ID: ");
                    String id2 = scanner.nextLine();
                    System.out.print("Name: ");
                    String name2 = scanner.nextLine();
                    System.out.print("Department: ");
                    String dept2 = scanner.nextLine();
                    System.out.print("Monthly Salary: ₹");
                    double salary2 = scanner.nextDouble();
                    System.out.print("Contract Duration (months): ");
                    int months = scanner.nextInt();
                    payroll.addEmployee(new ContractEmployee(id2, name2, dept2, salary2, months));
                    break;
                    
                case 3:
                    System.out.print("\nEmployee ID: ");
                    String id3 = scanner.nextLine();
                    System.out.print("Name: ");
                    String name3 = scanner.nextLine();
                    System.out.print("Department: ");
                    String dept3 = scanner.nextLine();
                    System.out.print("Hourly Rate: ₹");
                    double rate = scanner.nextDouble();
                    payroll.addEmployee(new HourlyEmployee(id3, name3, dept3, rate));
                    break;
                    
                case 4:
                    payroll.displayAllEmployees();
                    break;
                    
                case 5:
                    System.out.print("\nEmployee ID: ");
                    String empId = scanner.nextLine();
                    System.out.print("Year (YYYY): ");
                    int year = scanner.nextInt();
                    System.out.print("Month (1-12): ");
                    int month = scanner.nextInt();
                    payroll.generatePayslip(empId, YearMonth.of(year, month));
                    break;
                    
                case 6:
                    System.out.print("\nEmployee ID: ");
                    String empId2 = scanner.nextLine();
                    System.out.print("Hours Worked: ");
                    int hours = scanner.nextInt();
                    // Would need to implement setter in PayrollSystem
                    System.out.println("Feature implemented via direct object access");
                    break;
                    
                case 0:
                    System.out.println("\n╔═══════════════════════════════════════════╗");
                    System.out.println("║   Thank you for using Payroll System!     ║");
                    System.out.println("╚═══════════════════════════════════════════╝\n");
                    running = false;
                    break;
                    
                default:
                    System.out.println("\n✗ Invalid choice!");
            }
        }
        
        scanner.close();
    }
}

Explanation

Employee Types

  1. Permanent Employee:

    • Basic Salary + HRA (20%) + DA (15%) + TA (₹2000)
    • Full benefits and deductions
  2. Contract Employee:

    • Fixed monthly salary
    • Contract end date tracking
    • Limited benefits
  3. Hourly Employee:

    • Paid per hour worked
    • Overtime (1.5x) after 160 hours/month
    • Flexible working hours

Deduction Calculations

  1. Provident Fund: 12% of basic salary
  2. Income Tax (Simplified):
    • ₹0-25,000: 0%
    • ₹25,001-50,000: 5%
    • ₹50,001-1,00,000: 10%
    • Above ₹1,00,000: 20%
  3. Professional Tax: Fixed ₹200
  4. Insurance: Fixed ₹500

Key Features

  • Inheritance for different employee types
  • Progressive tax calculation
  • Detailed payslip generation
  • Number to words conversion
  • Overtime calculation for hourly employees

Try Yourself

  1. Bonuses: Add performance bonus functionality.
  2. Leave Management: Integrate leave tracking with salary deduction.
  3. Increment: Implement annual increment system.
  4. Loan: Add employee loan management and EMI deduction.
  5. Reimbursements: Track and add reimbursements to payslip.
  6. Bank Transfer: Generate bank transfer file (CSV).
  7. Payslip History: View all payslips for an employee.
  8. Department Reports: Generate department-wise salary reports.
  9. Tax Certificate: Generate Form 16 for tax filing.
  10. Attendance Integration: Link with attendance system for leave without pay.