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()
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())
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')
'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!')
""" 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