Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
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
Beispiel #4
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()