def hours_after_six_and_less_than_nine(shift): six_pm = TimeSheet.get_shift_end(shift).replace(hour=18, minute=0) duty_beyond_twelve = Weekday.duty_beyond_twelve_hours(shift) duty_beyond_nine = Weekday.duty_beyond_nine_hours(shift) overtime_duty = duty_beyond_twelve + duty_beyond_nine duty_remainder = TimeSheet.get_shift_length(shift) - overtime_duty start_plus_remainder = TimeSheet.get_shift_start( shift) + duty_remainder break_start = TimeSheet.get_break_start(shift) break_end = TimeSheet.get_break_end(shift) if TimeSheet.get_shift_start(shift) + duty_remainder > six_pm: if break_start and break_end < six_pm: # break STARTS and ENDS BEFORE 6pm hours_after_six_pm = (start_plus_remainder - six_pm ) - TimeSheet.get_break_duration(shift) return hours_after_six_pm elif break_start < six_pm < break_end: # break STARTS BEFORE and ENDS AFTER 6pm break_after_six_pm = TimeSheet.get_break_end(shift) - six_pm hours_after_six_pm = (start_plus_remainder - six_pm) - break_after_six_pm return hours_after_six_pm else: # no break spanning AFTER 6pm hours_after_six_pm = timedelta(hours=0, minutes=0) return hours_after_six_pm else: # no break within the reminder of duty up to 9hrs hours_after_six_pm = timedelta(hours=0, minutes=0) return hours_after_six_pm
def duty_beyond_nine_hours(shift): twelve_hours_duty = TimeSheet.get_shift_start(shift) + timedelta( hours=12) nine_hours_duty = TimeSheet.get_shift_start(shift) + timedelta(hours=9) break_start = TimeSheet.get_break_start(shift) break_end = TimeSheet.get_break_end(shift) # break STARTS and ENDS AFTER 9hrs and BEFORE 12hrs if (break_start > nine_hours_duty and break_end > nine_hours_duty) and break_end < twelve_hours_duty: duty_beyond_nine_hours = TimeSheet.get_break_end( shift) - nine_hours_duty return duty_beyond_nine_hours # break STARTS AFTER 9hrs and ENDS AFTER 12hrs elif break_start > nine_hours_duty and break_end > twelve_hours_duty: duty_beyond_nine_hours = TimeSheet.get_break_start( shift) - nine_hours_duty return duty_beyond_nine_hours # break STARTS BEFORE 9hrs and ENDS AFTER 9hrs duty elif break_start < nine_hours_duty < break_end < twelve_hours_duty: duty_beyond_nine_hours = TimeSheet.get_break_end( shift) - nine_hours_duty return duty_beyond_nine_hours else: # if no break between 9hrs and 12hrs duty, use the full 3hrs duty_beyond_nine_hours = timedelta(hours=3) return duty_beyond_nine_hours
def main(): file_path = Open(sys.argv[1]) employee_data = file_path.open_json_file() time_sheet = TimeSheet(employee_data) weekday = Weekday(employee_data) saturday = Saturday(employee_data) sunday = Sunday(employee_data) pays = Counter(weekday.get_weekday_pay()) + Counter(saturday.get_saturday_pay()) + \ Counter(sunday.get_sunday_pay()) deposit = 0 for value in pays.values(): deposit += value pays['total_pay'] = round(deposit, 3) with open('data.json', 'w') as file: json.dump(pays, file)
def duty_beyond_twelve_hours(shift): twelve_hours_duty = TimeSheet.get_shift_start(shift) + timedelta( hours=12) break_start = TimeSheet.get_break_start(shift) break_end = TimeSheet.get_break_end(shift) # break STARTS and ENDS AFTER 12hrs duty if break_start and break_end > twelve_hours_duty: duty_beyond_twelve_hours = (TimeSheet.get_shift_length(shift) - timedelta(hours=12)) - \ TimeSheet.get_break_duration(shift) return duty_beyond_twelve_hours # break STARTS BEFORE and ENDS AFTER 12hrs duty elif break_start < twelve_hours_duty < break_end: duty_beyond_twelve_hours = TimeSheet.get_break_end(shift) - \ (TimeSheet.get_shift_start(shift) + timedelta(hours=12)) return duty_beyond_twelve_hours else: # no break spanning AFTER 12hrs duty_beyond_twelve_hours = TimeSheet.get_shift_length( shift) - timedelta(hours=12) return duty_beyond_twelve_hours
def hours_before_six_and_less_than_nine(shift): six_pm = TimeSheet.get_shift_end(shift).replace(hour=18, minute=0) break_start = TimeSheet.get_break_start(shift) break_end = TimeSheet.get_break_end(shift) # shifts where 6pm comes BEFORE 9 hours duty if (TimeSheet.get_shift_start(shift) + timedelta(hours=9)) > TimeSheet.get_shift_end(shift) \ .replace(hour=18, minute=0) < TimeSheet.get_shift_end(shift).replace(hour=12, minute=0): if break_start and break_end < six_pm: # break STARTS and ENDS BEFORE 6pm hours_before_six_pm = ( TimeSheet.get_shift_start(shift) + six_pm) - TimeSheet.get_break_duration(shift) return hours_before_six_pm elif break_start < six_pm < break_end: # break STARTS BEFORE and ENDS AFTER 6pm break_before_six_pm = six_pm - TimeSheet.get_break_start(shift) hours_before_six_pm = ( six_pm - TimeSheet.get_shift_start(shift)) - break_before_six_pm return hours_before_six_pm else: # no break spanning BEFORE 6pm hours_before_six_pm = TimeSheet.get_shift_end(shift).replace(hour=18, minute=0) - \ TimeSheet.get_shift_start(shift) return hours_before_six_pm else: # no break BEFORE 6pm up to 9hrs hours_before_six_pm = TimeSheet.get_shift_end(shift).replace(hour=18, minute=0) - \ TimeSheet.get_shift_start(shift) return hours_before_six_pm
def get_weekday_pay(self): payslip = defaultdict(float) wage_rate = 0 for shift in self.data['shifts']: if TimeSheet.get_shift_start( shift).isoweekday() < 6: # day of week before saturday wage_level = float( shift['wageLevel']) # get wage level for shift if wage_level == 1: wage_rate = float(self.data['wageLevels']['1']) elif wage_level == 2: pass elif wage_level == 3: wage_rate = float(self.data['wageLevels']['3']) shift_length = TimeSheet.get_shift_length(shift) if shift_length > timedelta( hours=12): # shift lengths greater than 12hrs if shift.get('breakStart'): # has a break # pay over 12hrs duty pay_beyond_twelve_hours = \ round(Weekday.pay_beyond_twelve(Weekday.duty_beyond_twelve_hours(shift).total_seconds() / 3600, wage_rate), 3) if 'pay_beyond_twelve_hours' in payslip: payslip[ 'pay_beyond_twelve_hours'] += pay_beyond_twelve_hours payslip['duty_beyond_twelve_hours'] += \ Weekday.duty_beyond_twelve_hours(shift).total_seconds() / 3600 else: payslip[ 'pay_beyond_twelve_hours'] = pay_beyond_twelve_hours payslip['duty_beyond_twelve_hours'] = \ Weekday.duty_beyond_twelve_hours(shift).total_seconds() / 3600 # pay over 9hrs but less than 12hrs duty pay_beyond_nine_hours = \ round(Weekday.pay_beyond_nine(Weekday.duty_beyond_nine_hours(shift).total_seconds() / 3600, wage_rate), 3) if 'pay_beyond_nine_hours' in payslip: payslip[ 'pay_beyond_nine_hours'] += pay_beyond_nine_hours payslip['duty_beyond_nine_hours'] += \ Weekday.duty_beyond_nine_hours(shift).total_seconds() / 3600 else: payslip[ 'pay_beyond_nine_hours'] = pay_beyond_nine_hours payslip['pay_beyond_nine_hours'] = \ Weekday.duty_beyond_nine_hours(shift).total_seconds() / 3600 # pay less than 9hrs duty but BEFORE 6pm pay_beyond_six_pm = \ round(Weekday.pay_after_six_pm(Weekday.hours_after_six_and_less_than_nine(shift) .total_seconds() / 3600, wage_rate), 3) if 'pay_after_six_pm' in payslip: payslip['pay_after_six_pm'] += pay_beyond_six_pm payslip['duty_after_six_pm'] += \ Weekday.hours_after_six_and_less_than_nine(shift).total_seconds() / 3600 else: payslip['pay_after_six_pm'] = pay_beyond_six_pm payslip['duty_after_six_pm'] = \ Weekday.hours_after_six_and_less_than_nine(shift).total_seconds() / 3600 # pay less than 9hrs duty but BEFORE 6pm pay_before_six_pm = \ round(Weekday.pay_before_six_pm(Weekday.hours_before_six_and_less_than_nine(shift) .total_seconds() / 3600, wage_rate), 3) if 'pay_before_six_pm' in payslip: payslip['pay_before_six_pm'] += pay_before_six_pm payslip['duty_before_six_pm'] += \ Weekday.hours_before_six_and_less_than_nine(shift).total_seconds() / 3600 else: payslip['pay_before_six_pm'] = pay_before_six_pm payslip['duty_before_six_pm'] = \ Weekday.hours_before_six_and_less_than_nine(shift).total_seconds() /3600 if timedelta(hours=9) < shift_length < timedelta( hours=12): # duty over 9hrs and less than 12hrs if shift.get('breakStart'): # has a break # pay over 9hrs but less than 12hrs duty pay_beyond_nine_hours = \ round(Weekday.pay_beyond_nine(Weekday.duty_beyond_nine_hours(shift).total_seconds() / 3600, wage_rate), 3) if 'pay_beyond_nine_hours' in payslip: payslip[ 'pay_beyond_nine_hours'] += pay_beyond_nine_hours payslip['duty_beyond_nine_hours'] += \ Weekday.duty_beyond_nine_hours(shift).total_seconds() / 3600 else: payslip[ 'pay_beyond_nine_hours'] = pay_beyond_nine_hours payslip['duty_beyond_nine_hours'] = \ Weekday.duty_beyond_nine_hours(shift).total_seconds() / 3600 # pay less than 9hrs duty but BEFORE 6pm pay_beyond_six_pm = \ round(Weekday.pay_after_six_pm(Weekday.hours_after_six_and_less_than_nine(shift) .total_seconds() / 3600, wage_rate), 3) if 'pay_after_six_pm' in payslip: payslip['pay_after_six_pm'] += pay_beyond_six_pm payslip['duty_after_six_pm'] += \ Weekday.hours_after_six_and_less_than_nine(shift).total_seconds() / 3600 else: payslip['pay_after_six_pm'] = pay_beyond_six_pm payslip['duty_after_six_pm'] = \ Weekday.hours_after_six_and_less_than_nine(shift).total_seconds() / 3600 # pay less than 9hrs duty but BEFORE 6pm pay_before_six_pm = \ round(Weekday.pay_before_six_pm(Weekday.hours_before_six_and_less_than_nine(shift) .total_seconds() / 3600, wage_rate), 3) if 'pay_before_six_pm' in payslip: payslip['pay_before_six_pm'] += pay_before_six_pm payslip['duty_before_six_pm'] += \ Weekday.hours_before_six_and_less_than_nine(shift).total_seconds() / 3600 else: payslip['pay_before_six_pm'] = pay_before_six_pm payslip['duty_before_six_pm'] = \ Weekday.hours_before_six_and_less_than_nine(shift).total_seconds() / 3600 else: # has no break pay_beyond_nine_hours = round( Weekday.pay_beyond_nine(3.0, wage_rate), 3) if 'pay_beyond_nine_hours' in payslip: payslip[ 'pay_beyond_nine_hours'] += pay_beyond_nine_hours payslip['duty_beyond_nine_hours'] += 3.0 else: payslip[ 'pay_beyond_nine_hours'] = pay_beyond_nine_hours payslip['duty_beyond_nine_hours'] = 3.0 elif shift_length < timedelta(hours=9): # duty less than 9hrs if shift.get('breakStart'): # has a break # pay less than 9hrs duty but BEFORE 6pm pay_beyond_six_pm = \ round(Weekday.pay_after_six_pm(Weekday.hours_after_six_and_less_than_nine(shift) .total_seconds() / 3600, wage_rate), 3) if 'pay_after_six_pm' in payslip: payslip['pay_after_six_pm'] += pay_beyond_six_pm payslip['duty_after_six_pm'] += \ Weekday.hours_after_six_and_less_than_nine(shift).total_seconds() / 3600 else: payslip['pay_after_six_pm'] = pay_beyond_six_pm payslip['duty_after_six_pm'] = \ Weekday.hours_after_six_and_less_than_nine(shift).total_seconds() / 3600 # pay less than 9hrs duty but BEFORE 6pm pay_before_six_pm = \ round(Weekday.pay_before_six_pm(Weekday.hours_before_six_and_less_than_nine(shift) .total_seconds() / 3600, wage_rate), 3) if 'pay_before_six_pm' in payslip: payslip['pay_before_six_pm'] += pay_before_six_pm payslip['duty_before_six_pm'] += \ Weekday.hours_before_six_and_less_than_nine(shift).total_seconds() / 3600 else: payslip['pay_before_six_pm'] = pay_before_six_pm payslip['duty_before_six_pm'] = \ Weekday.hours_before_six_and_less_than_nine(shift).total_seconds() / 3600 else: # has no break pay_before_six_pm = \ round(Weekday.pay_before_six_pm(Weekday.hours_before_six_and_less_than_nine(shift) .total_seconds() / 3600, wage_rate), 3) if 'pay_before_six_pm' in payslip: payslip['pay_before_six_pm'] += pay_before_six_pm payslip['duty_before_six_pm'] += \ Weekday.hours_before_six_and_less_than_nine(shift).total_seconds() / 3600 else: payslip['pay_before_six_pm'] = pay_before_six_pm payslip['duty_before_six_pm'] = \ Weekday.hours_before_six_and_less_than_nine(shift).total_seconds() / 3600 return payslip
def loadProject(self): # load project if there is one if self.project: self.timesheet = TimeSheet(self.project)
class TimesheetGui(QDialog,Ui_Window): def __init__(self, *args): # if checkin status doesn't change, do a switch self.switch = True # check for the last set project home = os.path.expanduser('~') self.timesheetdir = timesheetdir = os.path.join(home, '.timesheets') if not os.path.isdir(timesheetdir): os.mkdir(timesheetdir) self.session = os.path.join(timesheetdir, '.session') if not os.path.isfile(self.session): self.project=None else: f = open(self.session) self.project = f.read() f.close() self.loadProject() # open tags file tags = os.path.join(timesheetdir, '.tags') if not os.path.isfile(tags): self.all_tags=[] else: f = open(tags) self.all_tags = f.readlines() f.close() # initalize UI QWidget.__init__(self, *args) self.setupUi(self) self.updateUI() # add tag completer tags = QtCore.QStringList(self.all_tags) self.completer = QCompleter(tags,self) self.tag_field.setCompleter(self.completer) def loadProject(self): # load project if there is one if self.project: self.timesheet = TimeSheet(self.project) def updateUI(self): if self.project: self.project_field.setText(self.project) self.project_field.setEnabled(False) self.tag_field.setEnabled(True) self.task_field.setEnabled(True) self.task_field.setFocus() self.sessionButton.setText('Checkout') self.status.setText('Checked In') self.status.setStyleSheet('color: green') else: self.project_field.clear() self.project_field.setEnabled(True) self.tag_field.setEnabled(False) self.tag_field.clear() self.task_field.setEnabled(False) self.task_field.clear() self.project_field.setFocus() self.sessionButton.setText('Checkin') self.status.setText('Checked Out') self.status.setStyleSheet('color: red') def rejected(self): sys.exit() def saveTags(self): f = open(os.path.join(self.timesheetdir,'.tags'),'a') tag = self.tag_field.text().__str__() try: if self.all_tags.index(tag) < 0: pass except ValueError: f.write('\n'+tag) f.close() def changeSessionStatus(self): self.switch = False if self.project: self.checkout() else: self.checkin() def checkout(self): self.timesheet.stop() self.timesheet = None self.project = None os.remove(self.session) self.updateUI() def checkin(self): self.project = self.project_field.text().__str__() if self.project == '': return f = open(self.session,'w') f.write(self.project) f.close() self.loadProject() self.timesheet.checkin() self.updateUI() def accept(self): if not self.project: self.reject() if self.switch: self.timesheet.stop() self.timesheet.start(self.task_field.toPlainText().__str__(),self.tag_field.text().__str__().split(' ')) self.saveTags() self.done(0) def keyPressEvent(self, event): pass
class TimesheetGui(QDialog, Ui_Window): def __init__(self, *args): # if checkin status doesn't change, do a switch self.switch = True # check for the last set project home = os.path.expanduser('~') self.timesheetdir = timesheetdir = os.path.join(home, '.timesheets') if not os.path.isdir(timesheetdir): os.mkdir(timesheetdir) self.session = os.path.join(timesheetdir, '.session') if not os.path.isfile(self.session): self.project = None else: f = open(self.session) self.project = f.read() f.close() self.loadProject() # open tags file tags = os.path.join(timesheetdir, '.tags') if not os.path.isfile(tags): self.all_tags = [] else: f = open(tags) self.all_tags = f.readlines() f.close() # initalize UI QWidget.__init__(self, *args) self.setupUi(self) self.updateUI() # add tag completer tags = QtCore.QStringList(self.all_tags) self.completer = QCompleter(tags, self) self.tag_field.setCompleter(self.completer) def loadProject(self): # load project if there is one if self.project: self.timesheet = TimeSheet(self.project) def updateUI(self): if self.project: self.project_field.setText(self.project) self.project_field.setEnabled(False) self.tag_field.setEnabled(True) self.task_field.setEnabled(True) self.task_field.setFocus() self.sessionButton.setText('Checkout') self.status.setText('Checked In') self.status.setStyleSheet('color: green') else: self.project_field.clear() self.project_field.setEnabled(True) self.tag_field.setEnabled(False) self.tag_field.clear() self.task_field.setEnabled(False) self.task_field.clear() self.project_field.setFocus() self.sessionButton.setText('Checkin') self.status.setText('Checked Out') self.status.setStyleSheet('color: red') def rejected(self): sys.exit() def saveTags(self): f = open(os.path.join(self.timesheetdir, '.tags'), 'a') tag = self.tag_field.text().__str__() try: if self.all_tags.index(tag) < 0: pass except ValueError: f.write('\n' + tag) f.close() def changeSessionStatus(self): self.switch = False if self.project: self.checkout() else: self.checkin() def checkout(self): self.timesheet.stop() self.timesheet = None self.project = None os.remove(self.session) self.updateUI() def checkin(self): self.project = self.project_field.text().__str__() if self.project == '': return f = open(self.session, 'w') f.write(self.project) f.close() self.loadProject() self.timesheet.checkin() self.updateUI() def accept(self): if not self.project: self.reject() if self.switch: self.timesheet.stop() self.timesheet.start(self.task_field.toPlainText().__str__(), self.tag_field.text().__str__().split(' ')) self.saveTags() self.done(0) def keyPressEvent(self, event): pass
def get_sunday_pay(self): payslip = defaultdict(float) wage_rate = 0 for shift in self.data['shifts']: day_of_week = TimeSheet.weekdays(shift) if day_of_week == 7: # get hours for Saturday wage_level = float( shift['wageLevel']) # get wage level for shift if wage_level == 1: wage_rate = float(self.data['wageLevels']['1']) elif wage_level == 2: pass elif wage_level == 3: wage_rate = float(self.data['wageLevels']['3']) if shift.get('breakStart'): # looks for shifts with a break shift_length = TimeSheet.get_shift_length(shift) break_duration = TimeSheet.get_break_duration(shift) nett_hours = shift_length - break_duration if nett_hours > timedelta( hours=12): # shift length greater than 12hrs plus_twelve_hours = nett_hours - timedelta(hours=12) plus_twelve = (plus_twelve_hours.total_seconds() / 3600 * wage_rate) * 2.25 plus_nine_hours = 3.0 plus_nine = (plus_nine_hours * wage_rate) * 2.25 normal_hours = (9.0 * wage_rate) * 1.95 if 'sunday_plus_twelve' in payslip: payslip['sunday_plus_twelve'] += round( plus_twelve, 3) else: payslip['sunday_plus_twelve'] = round( plus_twelve, 3) if 'sunday_plus_nine' in payslip: payslip['sunday_plus_nine'] += round(plus_nine, 3) else: payslip['sunday_plus_nine'] = round(plus_nine, 3) if 'sunday_normal' in payslip: payslip['sunday_normal'] += round(normal_hours, 3) else: payslip['sunday_normal'] = round(normal_hours, 3) elif nett_hours > timedelta(hours=9) <= timedelta( hours=12): # shift length 9-12hrs plus_nine_hours = nett_hours - timedelta(hours=9) plus_nine = (plus_nine_hours.total_seconds() / 3600 * wage_rate) * 2.25 normal_hours = (9.0 * wage_rate) * 1.95 if 'sunday_plus_nine' in payslip: payslip['sunday_plus_nine'] += round(plus_nine, 3) else: payslip['sunday_plus_nine'] = round(plus_nine, 3) if 'sunday_normal' in payslip: payslip['sunday_normal'] += round(normal_hours, 3) else: payslip['sunday_normal'] = round(normal_hours, 3) else: # shift length less than 9hrs normal_hours = (nett_hours.total_seconds() / 3600 * wage_rate) * 1.50 if 'sunday_normal' in payslip: payslip['sunday_normal'] += round(normal_hours, 3) else: payslip['sunday_normal'] = round(normal_hours, 3) else: # same logic as above with no break during the shift shift_length = TimeSheet.get_shift_length(shift) if shift_length > timedelta(hours=12): plus_twelve_hours = shift_length - timedelta(hours=12) plus_twelve = (plus_twelve_hours.total_seconds() / 3600 * wage_rate) * 2.25 plus_nine_hours = 3.0 plus_nine = (plus_nine_hours * wage_rate) * 2.25 normal_hours = (9.0 * wage_rate) * 1.95 if 'sunday_plus_twelve' in payslip: payslip['sunday_plus_twelve'] += round( plus_twelve, 3) else: payslip['sunday_plus_twelve'] = round( plus_twelve, 3) if 'sunday_plus_nine' in payslip: payslip['sunday_plus_nine'] += round(plus_nine, 3) else: payslip['sunday_plus_nine'] = round(plus_nine, 3) if 'sunday_normal' in payslip: payslip['sunday_normal'] += round(normal_hours, 3) else: payslip['sunday_normal'] = round(normal_hours, 3) elif shift_length > timedelta(hours=9) <= timedelta( hours=12): # shift length 9-12hrs plus_nine_hours = shift_length - timedelta(hours=9) plus_nine = (plus_nine_hours.total_seconds() / 3600 * wage_rate) * 2.25 normal_hours = (9.0 * wage_rate) * 1.95 if 'sunday_plus_nine' in payslip: payslip['sunday_plus_nine'] += round(plus_nine, 3) else: payslip['sunday_plus_nine'] = round(plus_nine, 3) if 'sunday_normal' in payslip: payslip['sunday_normal'] += round(normal_hours, 3) else: payslip['sunday_normal'] = round(normal_hours, 3) else: normal_hours = (shift_length.total_seconds() / 3600 * wage_rate) * 1.95 if 'sunday_normal' in payslip: payslip['sunday_normal'] += round(normal_hours, 3) else: payslip['sunday_normal'] = round(normal_hours, 3) return payslip