enum01.py

#!/usr/bin/python3
# ==================================================================
# https://www.youtube.com/watch?v=LrtnLEkOwFE
# 7 Python Code Smells: Olfactory Offenses To Avoid At All Costs
# ==================================================================

"""
Very advanced Employee management system.
"""

from dataclasses import dataclass
from typing import List
from enum import Enum, auto

# the fixed number of vacation days that ca be paid out.
FIXED_VACATION_DAYS_PAYOUT = 5 

class Role(Enum):
   """ Employee rolls."""   
   PRESIDENT = auto()
   VICEPRESIDENT = auto()
   MANAGER = auto()
   LEAD = auto()
   WORKER = auto()
   INTERN = auto()
      
@dataclass
class Employee:
    """Basic Employee Data"""
    
    name: str
    role: Role
    vacation_days: int = 25
    
    def take_a_holiday(self, payout: bool) -> None:
       """let the employee take a single holiday, or pay out 5 holidays."""
       if payout:
          # check ther are a enough holidays left over for a payout.
          if self.vacation_days < FIXED_VACATION_PAYOUT:
             raise ValueError(
                f'You don\'t have enough holidays left over for a payout.\
                   Remaining Holidays: {self.vacation_days}.'
             )
          try:
             self.vacation_days -= FIXED_HOLIDAY_DAYS_PAYOUT
             print('Paying out a holiday. Holidays left: {self.vacation_days}')
          except Exception:
             # this should never happen
             pass
       else:
          if self.vacation_days < 1:
             raise ValueError(
                'You don\' have any holidays left. Now back to work you!')
          self.vacation_days -= 1
          print('have fun on your holiday. Don\'t foregt to check your emails!') 

@dataclass
class HourlyEmployee(Employee):
   """Employee that\s paint based on the number of hours worked"""
   hourly_rate: float = 50
   ammount: int = 0
   
@dataclass
class SalariedEmployee(Employee):
   """Employee that\'s paid based on a fixed monthly salary."""
   monthly_salary: float = 5000
           
class Company:
   """ represents a company with employees."""
   def __init__(self) -> None:
      self.employees: list[Employee] = []

   def add_employee(self,employee:Employee) -> None:
      """Add an employee to the list of employees."""
      self.employees.append(employee)
   
   # ==================================================================
   # could use a list comprrehension
   # def find_employee(self, role: Role) -> List[Emeployee]:
   #    return [employee for employee in self.employees if employee.role == role]
   # ==================================================================
   def find_employees(self, role: Role) -> List[Employee]:
       """Add an employee to the list of employeees"""
       employees = []
       for employee in self.employees:
           if employee.role == role:
               employees.append(employee)
        
   def pay_employee(self,employee: Employee) -> None:
      """ pay an employee."""
      if isinstance(employee, SalariedEmployee):
         print(
            f'Paying employee {employee.name} a monthly salary of ' +
            f'${employee.monthly_salary}.')
      elif isinstance(employee.HourlyEmployee):
         print(
            f'Paying employee {employee.name} a hourly rate of ' +
            f'${employee.hourly_rate} for {employee.amount} hours.')


# ---- main -------------------------------------------------------

company = Company()

company.add_employee(SalariedEmployee(name="Tom", role=Role.MANAGER))
company.add_employee(SalariedEmployee(name="Dick", role=Role.WORKER))
company.add_employee(SalariedEmployee(name="Harry", role=Role.INTERN))
company.add_employee(SalariedEmployee(name="Judy", role=Role.PRESIDENT))

print(company.find_employees(Role.PRESIDENT))
print(company.find_employees(Role.VICEPRESIDENT))
print(company.find_employees(Role.MANAGER))
print(company.find_employees(Role.WORKER))
print(company.find_employees(Role.INTERN))
company.pay_employee(company.employees[0])
company.employees[0].take_a_holiday(False)