def _on_password_save(
        view,
        dialog,
        employee_id,
        old_pass: str,  # pylint: disable=too-many-arguments
        password: str,
        password_confirm: str,
        require_old=True):
    employee = Employee.read(employee_id)

    if require_old and sha_hash(old_pass) != employee.password:
        view.show_error('Error', 'Old password does not match!')
        return

    if password != password_confirm:
        view.show_error('Error', 'New Passwords do not match!')
        return

    if not is_valid_against('password', password):
        view.show_error(
            'Error',
            'Passwords must have at least 9 characters (with at least '
            '1 number, 1 special character, and upper and lowercase '
            'characters)!')
        return

    Employee.read(employee_id).update_password(password)

    view.set_status('Changing password successful!')
    view.show_info('Info', 'Changing password successful!')
    dialog.destroy()
Пример #2
0
def root_account_install():
    """
    Adds the superadmin root account to the database if it isn't there
    :return:
    """
    if Employee.read(-1) is None:
        Employee.create(Employee({
            'id': -1,
            'password': sha_hash(ROOT_DEFAULT_PASS),
            'role': 'Admin',
            'last_name': 'Admin',
            'first_name': 'Root',
            'user_group_id': 0,
            'start_date': datetime.date.today(),
            'date_of_birth': datetime.date.today(),
            'sex': -1,
            'address_line1': 'INVALID',
            'city': 'INVALID',
            'state': 'INVALID',
            'zipcode': '000',
            'classification_id': 1,
            'paymethod_id': 1,
            'created_at': datetime.datetime.now(),
            'modified_at': datetime.datetime.now(),
            'date_left': datetime.date.today(),
            'notes': ''
        }))
def run_payroll(output_filepath: str):
    """
    Runs payroll
    :param output_filepath: file output
    :return: None
    """
    employees = Employee.read_all()
    now = datetime.datetime.now()
    timestamp = now.strftime('%d-%m-%Y %H:%M')
    with open(output_filepath, 'a') as file:
        for employee in employees:
            balance = employee.get_balance()

            if balance > 0:
                if employee.payment_method.name == MailMethod.name:
                    file.write(
                        f"[{timestamp}] Mail {balance:.2f} to "
                        f"{employee.get_name()} to "
                        f"{employee.address_line1} {employee.city} {employee.zipcode}\n"
                    )
                elif employee.payment_method.name == DirectMethod.name:
                    file.write(
                        f"[{timestamp}] Transfer {balance:.2f} to "
                        f"{employee.get_name()} to "
                        f"{employee.address_line1} {employee.city} {employee.zipcode}\n"
                    )
    def new_receipt(self):
        """
        Shows the add receipt dialog and saves it
        :return: None
        """
        def on_save(dialog, employee_id: int, amount: float):
            try:
                amount = float(amount)
            except ValueError:
                self.view.show_error('Error', 'Invalid amount given!')
                return

            if Employee.read(employee_id):
                receipt = Receipt({'user_id': employee_id, 'amount': amount})
                try:
                    Receipt.create(receipt)
                    self.view.show_info('Info',
                                        'Receipt created successfully!')
                except SecurityException as error:
                    self.view.show_error('Error',
                                         f'Unable to create receipt: {error}')
                    return
                except ChangeRequestException:
                    self.view.show_info(
                        'Info', 'A change request has been created '
                        'and will be reviewed.')

            self.view.set_status('Receipt creation successful!')
            dialog.destroy()

        AddReceiptDialog({'save': on_save}, Employee.read_all())
Пример #5
0
    def login(self, username, password):
        """
        If authentication is successful, the database window is spawned

        :param username: str
        :param password: str
        :return: None
        """
        if not self.view.validate():
            return

        try:
            int(username)
        except ValueError:
            self.view.show_error(
                'Invalid Employee ID', 'Please ensure '
                'your ID is entered in correctly.')
            return

        authenticated = Employee.authenticate(username, password)
        if authenticated is not None:
            store.SECURITY_LAYER = SecurityLayer(authenticated)
            print("Logged in as user ID", authenticated.id)
            self.view.destroy()
            DatabaseController().show()
        else:
            self.view.show_error(title='Error',
                                 message='Credentials incorrect!')
 def new_employee(self):
     """
     When New is pressed.
     :return: None
     """
     self.view.new_employee(self.new_id,
                            Employee.new_empty().to_view_model())
     self.new_id += 1
    def save(self):
        """
        When Save is pressed, the change is either performed, or a change request is submitted
        :return: None
        """
        self.view.on_before_save()
        change_request_submitted = False
        for employee_id in self.view.table.unsaved:
            view_model = self.view.table.model.data[employee_id]

            is_new = False
            if isinstance(employee_id, str) and "NEW" in employee_id:
                view_model[Employee.view_columns['id']] = None
                is_new = True

            try:
                employee = Employee.from_view_model(view_model)
                if is_new:
                    Employee.create(employee)
                else:
                    Employee.update(employee)
            except ChangeRequestException:
                change_request_submitted = True
            except SecurityException as error:
                self.view.highlight_invalid_rows([employee_id])
                self.view.show_error('Error', f'Access Denied\n{error}')
                return
            except ValidationException as error:
                self.view.highlight_invalid_cell(
                    employee_id, Employee.view_columns[error.database_field])
                self.view.show_error('Error', f'Invalid data: {error}')
                self.view.set_status(f'Invalid data: {error}')
                return

        if change_request_submitted:
            self.view.show_info('Success', 'Request to Change Submitted!')
            self.view.set_status(
                f'Request to Change {len(self.view.table.unsaved)} '
                f'employees Submitted!')
        else:
            self.view.set_status(
                f'Saved {len(self.view.table.unsaved)} employees successfully!'
            )
            self.view.master.bell()
        self.refresh()
def import_employees(filename: str, from_cmd=True):
    """
    Imports Employees in the following format:

    ID,Name,Address,City,State,Zip,Classification,PayMethod,Salary,Hourly,Commission,Route,Account

    with headers included

    Example:
        ID,Name,Address,City,State,Zip,Classification,PayMethod,Salary,Hourly,Commission,Route,Account  # pylint: disable=line-too-long
        688997,Karina Gay,998 Vitae St.,Atlanta,GA,45169,1,1,45884.99,46.92,34,30417353-K,465794-3611  # pylint: disable=line-too-long

    :param filepath: path to file
    :param from_cmd: bool if calling from cmd line
    :return: None
    """
    i = 0
    for row in _import_csv(filename, has_headers=True):
        names = _split_names(row[1])
        Employee.create(
            Employee({
                'id': row[0],
                'role': 'Viewer',
                'first_name': names[0],
                'last_name': names[1],
                'address_line1': row[2],
                'address_line2': '',
                'city': row[3],
                'state': row[4],
                'zipcode': row[5],
                'classification_id': int(row[6]),
                'paymethod_id': int(row[7]),
                'salary': row[8],
                'hourly_rate': row[9],
                'commission_rate': row[10],
                'bank_routing': row[11],
                'bank_account': row[12],
            }))
        print('Importing Emp#', row[0])
        i += 1

    print(f'Imported {i} employees successfully')
    if not from_cmd:
        messagebox.showinfo("showinfo", f'Imported {i} employees successfully')
 def delete(self):
     """
     When Delete is pressed, the change is either performed, or a change request is submitted
     :return: None
     """
     if self.view.show_confirm(
             title='Confirm Employee Deletion',
             message='Are you sure you want to delete the employee(s)?'):
         ids = self.view.table.get_selectedRecordNames()
         for employee_id in ids:
             try:
                 Employee.destroy(employee_id)
             except SecurityException:
                 self.view.show_error(
                     'Access Denied', 'Insufficient permission to delete '
                     'selected employees')
                 self.refresh()
                 break
         self.view.show_info(
             'Deletion Successful', 'The selected employee(s) '
             'were deleted successfully!')
         self.refresh()
def import_timesheets(filepath: str, from_cmd=True):
    """
    Imports Timesheets in the following format:

    [employee ID],[time in hours],[time in hours], ...

    Example:
        426824,7.4,6.5,5.7,8.0,6.9,7.5,6.5,7.5
        934003,5.8,7.5,5.8,4.8,5.9,4.8,4.0,6.6,5.5,7.2

    :param filepath: path to file
    :param from_cmd: bool if calling from cmd line
    :return: None
    """
    employees_not_found = []

    i = 0
    for row in _import_csv(filepath):
        employee_id = int(row[0])

        if not Employee.read(employee_id):
            print(f'No Employee#{employee_id} exists, ignoring')
            employees_not_found.append(employee_id)
            continue

        timesheets = row[1:]

        for time_in_hours in timesheets:
            datetime_end = datetime.datetime.now()
            datetime_begin = datetime_end - datetime.timedelta(
                seconds=(float(time_in_hours) * 3600))

            TimeSheet.create(
                TimeSheet({
                    'user_id': employee_id,
                    'datetime_end': datetime_end,
                    'datetime_begin': datetime_begin
                }))
            print('Importing TimeSheet#', i, 'for Emp#', employee_id)
            i += 1

    print(f'Imported {i} timesheets successfully')
    if not from_cmd:
        if len(employees_not_found) > 0:
            messagebox.showinfo(
                "showwarning", f'Imported {i} timesheets successfully. '
                f'However, the following'
                f'employee ID\'s were not found: {employees_not_found}')
        else:
            messagebox.showinfo("showinfo",
                                f'Imported {i} timesheets successfully')
    def load(self):
        """
        Loads all employees and displays them on the table
        :return: None
        """
        employees = Employee.read_all()
        i = 0
        for employee in employees:
            i += 1
            self.view.add_to_result(
                employee.id,
                employee.to_view_model(security_layer=store.SECURITY_LAYER))

        self.view.table.autoResizeColumns()
    def new_timesheet(self):
        """
        Shows the add timesheet dialog and saves it
        :return: None
        """
        def on_save(
                dialog,
                employee_id: int,
                date: datetime.date,  # pylint: disable=too-many-arguments
                hour_in,
                min_in,
                hour_out,
                min_out):
            try:
                hour_in = int(hour_in)
                min_in = int(min_in)
                hour_out = int(hour_out)
                min_out = int(min_out)
            except ValueError:
                self.view.show_error('Error', 'Invalid dates given!')
                return

            time_begin = datetime.datetime.strptime(f"{hour_in} {min_in}",
                                                    "%H %M").time()
            time_end = datetime.datetime.strptime(f"{hour_out} {min_out}",
                                                  "%H %M").time()
            datetime_begin = datetime.datetime.combine(date, time_begin)
            datetime_end = datetime.datetime.combine(date, time_end)

            if Employee.read(employee_id):
                timesheet = TimeSheet({
                    'user_id': employee_id,
                    'datetime_begin': datetime_begin,
                    'datetime_end': datetime_end,
                })
                try:
                    TimeSheet.create(timesheet)
                    self.view.show_info('Success',
                                        'Timesheet created successfully!')
                except SecurityException:
                    self.view.show_error('Error', 'Access Denied')
                    return
                except ChangeRequestException:
                    self.view.show_info(
                        'Info', 'A change request has been created '
                        'and will be reviewed.')
            self.view.set_status('Timesheet creation successful!')
            dialog.destroy()

        AddTimesheetDialog({'save': on_save}, Employee.read_all())
    def change_password(self):
        """
        Shows the change others' passwords dialog and saves it
        :return: None
        """
        def on_save(dialog, employee_id, password: str, password_confirm: str):
            _on_password_save(self.view,
                              dialog,
                              employee_id,
                              None,
                              password,
                              password_confirm,
                              require_old=False)

        PasswordDialog({'save': on_save}, Employee.read_all())
def import_receipts(filepath: str, from_cmd=True):
    """
    Imports Receipts in the following format:

    [employee ID],[receipt amount],[receipt amount], ...

    Example:
        160769,63.02,163.42,140.06,84.15
        377013,220.89,238.57,218.84


    :param filepath: path to file
    :param from_cmd: bool if calling from cmd line
    :return: None
    """
    employees_not_found = []

    i = 0
    for row in _import_csv(filepath):
        employee_id = int(row[0])

        if not Employee.read(employee_id):
            print(f'No Employee#{employee_id} exists, ignoring')
            employees_not_found.append(employee_id)
            continue

        receipts = row[1:]

        for receipt in receipts:
            Receipt.create(Receipt({
                'user_id': employee_id,
                'amount': receipt
            }))
            print('Importing Receipt#', i, 'for Emp#', employee_id)
            i += 1

    print(f'Imported {i} receipts successfully')
    if not from_cmd:
        if len(employees_not_found) > 0:
            messagebox.showinfo(
                "showwarning", f'Imported {i} receipts '
                f'successfully. However, the following'
                f'employee ID\'s were not found: {employees_not_found}')
        else:
            messagebox.showinfo("showinfo",
                                f'Imported {i} receipts successfully')
Пример #15
0
            'department_id': 0,
            'role': 'Accounting',
            'last_name': 'doe',
            'first_name': 'john',
            'start_date': datetime.date.today(),
            'date_of_birth': datetime.date.today(),
            'sex': 0,
            'address_line1': 'Test Street',
            'city': 'Test City',
            'state': 'Test State',
            'zipcode': '0000',
            'classification_id': 0,
            'paymethod_id': 0,
            'salary': 1.0
        }
        mymodel = Employee(data)
        saved = Employee.create(mymodel)

        security_layer = SecurityLayer(saved)

        saved.salary = 2.0
        saved.hourly_rate = 10
        try:
            Employee.update(saved)
            print('Changed w/o change request')
            assert False
        except SecurityException as error:
            print(error)
            assert False
        except ChangeRequestException as error:
            print('change request entered!')
Пример #16
0
"""
Tests basic CRUD ops.

Outdated
"""
import os

from lib.layer.security import SecurityLayer
from lib.model.employee import Employee
from lib.repository.db import database_setup

if __name__ == '__main__':
    database_setup({'DB_URL': 'sqlite+pysqlite:///empdat.db'})

    data = {'last_name': 'doe', 'role': 'Viewer'}
    mymodel = Employee(data)
    # print(mymodel.data)

    mymodel.first_name = 'john'
    # print(mymodel.to_dict())

    saved = Employee.create(mymodel)
    security_layer = SecurityLayer(saved)
    # Employee.destroy('XYZ')

    test = Employee.read(saved.id)
    # print(test.to_dict())

    test2 = Employee.read_all()
    print(test2)
    print('---')
 def load_relationships(self):
     self.author = Employee.read(self.author_user_id)
     try:
         self.approved_by = Employee.read(self.approved_by_user_id)
     except AttributeError:
         self.approved_by = None