def _fetch_preceding_days_worked_streak(self): """See how many days in an row the worker has worked prior to the beginning of this week. """ logger.debug("Fetching preceding day streak for user %s" % self.user_id) # Search up to max_consecutive_workdays - beyond doesn't matter streak = 0 for t in range(self.environment.max_consecutive_workdays): # Build search search_end = self.environment.start - timedelta(days=t) search_start = search_end - timedelta(days=1) shifts_obj = self._get_role_client().get_shifts( start=dt_to_query_str(search_start - timedelta( hours=config.MAX_HOURS_PER_SHIFT)), end=dt_to_query_str(search_end), user_id=self.user_id, ) if len([ s for s in shifts_obj if (Shift(s).start >= search_start) > 0 ]): streak += 1 else: # Streak over! return streak return streak
def _fetch_preceding_day_worked(self): """Fetch from api whether worker worked the day before this week began. Used for consecutive days off. """ logger.debug("Fetching preceding day worked for user %s" % self.user_id) search_end = self.environment.start search_start = search_end - timedelta(days=1) shifts_objs = self._get_role_client().get_shifts( start=dt_to_query_str(search_start), end=dt_to_query_str(search_end), user_id=self.user_id, ) for shift in shifts_objs: # Edge case - mark the first day of week as # active if the person works past midnight if shift.stop > self.environment.start: self.active_days[dt_to_day( self.environment.datetime_utc_to_local(shift.stop))] = True self.preceding_day_worked = len(shifts_objs) > 0
def _fetch_existing_shifts(self): """Look for fixed shifts and other stuff""" logger.debug("Fetching existing shifts for user %s" % self.user_id) self.existing_shifts = [] shifts_obj_raw = self._get_role_client().get_shifts( start=dt_to_query_str(self.environment.start - timedelta(hours=config.MAX_HOURS_PER_SHIFT)), end=dt_to_query_str(self.environment.stop), user_id=self.user_id) shifts_obj = [] for s in shifts_obj_raw: shifts_obj.append(Shift(s)) for s in [s for s in shifts_obj if s.start >= self.environment.start]: logger.info("Found existing shift %s for user %s" % (s.shift_id, self.user_id)) self.existing_shifts.append(s) # Also decrease hours to be scheduled by that self.min_hours_per_workweek -= 1.0 * s.total_minutes( ) / MINUTES_PER_HOUR if self.min_hours_per_workweek < 0: self.min_hours_per_workweek = 0 self.max_hours_per_workweek -= 1.0 * s.total_minutes( ) / MINUTES_PER_HOUR if self.max_hours_per_workweek < 0: self.min_hours_per_workweek = 0 self.max_hours_per_workweek -= 1.0 * s.total_minutes( ) / MINUTES_PER_HOUR if self.max_hours_per_workweek < 0: self.max_hours_per_workweek = 0
def _process_task(self, task): # 1. Fetch schedule self.org = self.client.get_organization(task.data.get( "organization_id")) self.loc = self.org.get_location(task.data.get("location_id")) self.role = self.loc.get_role(task.data.get("role_id")) self.sched = self.role.get_schedule(task.data.get("schedule_id")) env = Environment( organization_id=task.data.get("organization_id"), location_id=task.data.get("location_id"), role_id=task.data.get("role_id"), schedule_id=task.data.get("schedule_id"), tz_string=self.loc.data.get("timezone"), start=self.sched.data.get("start"), stop=self.sched.data.get("stop"), day_week_starts=self.org.data.get("day_week_starts"), min_minutes_per_workday=self.role.data.get("min_hours_per_workday") * MINUTES_PER_HOUR, max_minutes_per_workday=self.role.data.get("max_hours_per_workday") * MINUTES_PER_HOUR, min_minutes_between_shifts=self.role.data.get( "min_hours_between_shifts") * MINUTES_PER_HOUR, max_consecutive_workdays=self.role.data.get( "max_consecutive_workdays")) user_objs = self.role.get_workers(archived=False) employees = [] for e in user_objs: new_e = Employee( user_id=e.data["id"], min_hours_per_workweek=e.data["min_hours_per_workweek"], max_hours_per_workweek=e.data["max_hours_per_workweek"], environment=env, ) # check whether employee even has availability to work if week_sum(new_e.availability) > new_e.min_hours_per_workweek: employees.append(new_e) if len(employees) is 0: logger.info("No employees") return # Get the shifts shift_api_objs = self.role.get_shifts(start=dt_to_query_str(env.start), end=dt_to_query_str(env.stop), user_id=UNASSIGNED_USER_ID) # Convert api objs to something more manageable shifts = [] for s in shift_api_objs: shifts.append(Shift(s)) if len(shifts) is 0: logger.info("No unassigned shifts") return # Run the calculation a = Assign(env, employees, shifts) a.calculate() a.set_shift_user_ids()