示例#1
0
 def _get_current_accrual_plan_level_id(self, date, level_ids=False):
     """
     Returns a pair (accrual_plan_level, idx) where accrual_plan_level is the level for the given date
      and idx is the index for the plan in the ordered set of levels
     """
     self.ensure_one()
     if not self.accrual_plan_id.level_ids:
         return (False, False)
     # Sort by sequence which should be equivalent to the level
     if not level_ids:
         level_ids = self.accrual_plan_id.level_ids.sorted('sequence')
     current_level = False
     current_level_idx = -1
     for idx, level in enumerate(level_ids):
         if date >= self.date_from + get_timedelta(level.start_count,
                                                   level.start_type):
             current_level = level
             current_level_idx = idx
     # If transition_mode is set to `immediately` or we are currently on the first level
     # the current_level is simply the first level in the list.
     if current_level_idx <= 0 or self.accrual_plan_id.transition_mode == "immediately":
         return (current_level, current_level_idx)
     # In this case we have to verify that the 'previous level' is not the current one due to `end_of_accrual`
     level_start_date = self.date_from + get_timedelta(
         current_level.start_count, current_level.start_type)
     previous_level = level_ids[current_level_idx - 1]
     # If the next date from the current level's start date is before the last call of the previous level
     # return the previous level
     if current_level._get_next_date(
             level_start_date) < previous_level._get_next_date(
                 level_start_date):
         return (previous_level, current_level_idx - 1)
     return (current_level, current_level_idx)
示例#2
0
 def _process_accrual_plans(self):
     """
     This method is part of the cron's process.
     The goal of this method is to retroactively apply accrual plan levels and progress from nextcall to today
     """
     today = fields.Date.today()
     first_allocation = _("""This allocation have already ran once, any modification won't be effective to the days allocated to the employee. If you need to change the configuration of the allocation, cancel and create a new one.""")
     for allocation in self:
         level_ids = allocation.accrual_plan_id.level_ids.sorted('sequence')
         if not level_ids:
             continue
         if not allocation.nextcall:
             first_level = level_ids[0]
             first_level_start_date = allocation.date_from + get_timedelta(first_level.start_count, first_level.start_type)
             if today < first_level_start_date:
                 # Accrual plan is not configured properly or has not started
                 continue
             allocation.lastcall = max(allocation.lastcall, first_level_start_date)
             allocation.nextcall = first_level._get_next_date(allocation.lastcall)
             allocation._message_log(body=first_allocation)
         days_added_per_level = defaultdict(lambda: 0)
         while allocation.nextcall <= today:
             (current_level, current_level_idx) = allocation._get_current_accrual_plan_level_id(allocation.nextcall)
             nextcall = current_level._get_next_date(allocation.nextcall)
             # Since _get_previous_date returns the given date if it corresponds to a call date
             # this will always return lastcall except possibly on the first call
             # this is used to prorate the first number of days given to the employee
             period_start = current_level._get_previous_date(allocation.lastcall)
             period_end = current_level._get_next_date(allocation.lastcall)
             # Also prorate this accrual in the event that we are passing from one level to another
             if current_level_idx < (len(level_ids) - 1) and allocation.accrual_plan_id.transition_mode == 'immediately':
                 next_level = level_ids[current_level_idx + 1]
                 current_level_last_date = allocation.date_from + get_timedelta(next_level.start_count, next_level.start_type) - relativedelta(days=1)
                 if allocation.nextcall != current_level_last_date:
                     nextcall = min(nextcall, current_level_last_date)
             days_added_per_level[current_level] += allocation._process_accrual_plan_level(
                 current_level, period_start, allocation.lastcall, period_end, allocation.nextcall)
             allocation.lastcall = allocation.nextcall
             allocation.nextcall = nextcall
         if days_added_per_level:
             number_of_days_to_add = 0
             for value in days_added_per_level.values():
                 number_of_days_to_add += value
             # Let's assume the limit of the last level is the correct one
             allocation.write({'number_of_days': min(allocation.number_of_days + number_of_days_to_add, current_level.maximum_leave)})
示例#3
0
 def _process_accrual_plans(self):
     """
     This method is part of the cron's process.
     The goal of this method is to retroactively apply accrual plan levels and progress from nextcall to today
     """
     today = fields.Date.today()
     first_allocation = _(
         """This allocation have already ran once, any modification won't be effective to the days allocated to the employee. If you need to change the configuration of the allocation, cancel and create a new one."""
     )
     for allocation in self:
         level_ids = self.accrual_plan_id.level_ids.sorted('sequence')
         if not level_ids:
             continue
         if not allocation.nextcall:
             first_level = level_ids[0]
             first_level_start_date = allocation.date_from + get_timedelta(
                 first_level.start_count, first_level.start_type)
             if today < first_level_start_date:
                 # Accrual plan is not configured properly or has not started
                 continue
             allocation.lastcall = max(allocation.lastcall,
                                       first_level_start_date)
             allocation.nextcall = first_level._get_next_date(
                 allocation.lastcall)
             allocation._message_log(body=first_allocation)
         days_added_per_level = defaultdict(lambda: 0)
         while allocation.nextcall <= today:
             current_level = allocation._get_current_accrual_plan_level_id(
                 allocation.nextcall)
             nextcall = current_level._get_next_date(allocation.nextcall)
             days_added_per_level[
                 current_level] += allocation._process_accrual_plan_level(
                     current_level, allocation.lastcall,
                     allocation.nextcall)
             allocation.lastcall = allocation.nextcall
             allocation.nextcall = nextcall
         if days_added_per_level:
             number_of_days_to_add = 0
             for value in days_added_per_level.values():
                 number_of_days_to_add += value
             # Let's assume the limit of the last level is the correct one
             allocation.write({
                 'number_of_days':
                 min(allocation.number_of_days + number_of_days_to_add,
                     current_level.maximum_leave)
             })
示例#4
0
    def _get_accrual_values(self, allocation_create_date):
        """
        This method returns all the accrual linked to their accrual_plan with the updated dynamic parameters depending
        on the date.
        :return: dict: {accrual_id, accrual_start, accrual_stop, nextcall, sufficient_seniority}
         where accrual_start and accrual_stop are start and stop of the current period
        """
        today = fields.Date.context_today(self, )
        results = []
        for accrual in self:
            seniority = allocation_create_date + get_timedelta(
                accrual.start_count, accrual.start_type)
            frequency = accrual.frequency
            if frequency == 'daily':
                accrual_start = max(today, seniority.date())
                accrual_stop = accrual_start + relativedelta(days=1)
                nextcall = accrual_stop
            elif frequency == 'weekly':
                min_accrual_date = max(today, seniority.date())
                if min_accrual_date.isoweekday() == DAYS.index(
                        accrual.week_day):
                    accrual_stop = min_accrual_date
                else:
                    accrual_stop = accrual._get_next_weekday(
                        min_accrual_date, accrual.week_day)
                accrual_start = accrual_stop - relativedelta(days=7)
                nextcall = accrual._get_next_weekday(min_accrual_date,
                                                     accrual.week_day)
            elif frequency == 'bimonthly':
                if today.day <= accrual.first_day:
                    accrual_start = datetime.date(
                        today.year, today.month,
                        accrual.second_day) - relativedelta(months=1)
                    accrual_stop = datetime.date(today.year, today.month,
                                                 accrual.first_day)
                    nextcall = datetime.date(today.year, today.month,
                                             accrual.second_day)
                else:
                    if today.day <= accrual.second_day:
                        accrual_start = datetime.date(today.year, today.month,
                                                      accrual.first_day)
                        accrual_stop = datetime.date(today.year, today.month,
                                                     accrual.second_day)
                        nextcall = datetime.date(
                            today.year, today.month,
                            accrual.first_day) + relativedelta(months=1)
                    else:
                        accrual_start = datetime.date(today.year, today.month,
                                                      accrual.second_day)
                        accrual_stop = datetime.date(
                            today.year, today.month,
                            accrual.first_day) + relativedelta(months=1)
                        nextcall = datetime.date(
                            today.year, today.month,
                            accrual.second_day) + relativedelta(months=1)
            elif frequency == 'monthly':
                if today.day <= accrual.first_day:
                    accrual_start = datetime.date(
                        today.year, today.month,
                        accrual.first_day) - relativedelta(months=1)
                    accrual_stop = datetime.date(today.year, today.month,
                                                 accrual.first_day)
                    nextcall = datetime.date(
                        today.year, today.month,
                        accrual.first_day) + relativedelta(months=1)
                else:
                    accrual_start = datetime.date(today.year, today.month,
                                                  accrual.first_day)
                    accrual_stop = datetime.date(
                        today.year, today.month,
                        accrual.first_day) + relativedelta(months=1)
                    nextcall = datetime.date(
                        today.year, today.month,
                        accrual.first_day) + relativedelta(months=2)
            elif frequency == 'biyearly':
                first_month = MONTHS.index(accrual.first_month) + 1
                second_month = MONTHS.index(accrual.second_month) + 1
                potential_first_accrual_date = datetime.date(
                    today.year, first_month, accrual.first_month_day)
                potential_second_accrual_date = datetime.date(
                    today.year, second_month, accrual.second_month_day)
                if today <= potential_first_accrual_date:
                    accrual_start = potential_second_accrual_date - relativedelta(
                        years=1)
                    accrual_stop = potential_first_accrual_date
                    nextcall = potential_second_accrual_date
                else:
                    if today <= potential_second_accrual_date:
                        accrual_start = potential_first_accrual_date
                        accrual_stop = potential_second_accrual_date
                        nextcall = potential_first_accrual_date + relativedelta(
                            years=1)
                    else:
                        accrual_start = potential_second_accrual_date
                        accrual_stop = potential_first_accrual_date + relativedelta(
                            years=1)
                        nextcall = potential_first_accrual_date + relativedelta(
                            years=1)
            elif frequency == 'yearly':
                month = MONTHS.index(accrual.yearly_month) + 1
                potential_accrual_date = datetime.date(today.year, month,
                                                       accrual.yearly_day)
                if today <= potential_accrual_date:
                    accrual_start = potential_accrual_date - relativedelta(
                        years=1)
                    accrual_stop = potential_accrual_date
                    nextcall = potential_accrual_date + relativedelta(years=1)
                else:
                    accrual_start = potential_accrual_date
                    accrual_stop = potential_accrual_date + relativedelta(
                        years=1)
                    nextcall = accrual_stop

            results.append({
                'accrual_level_id':
                accrual.id,
                'start_after':
                accrual.start_count,
                'accrual_start':
                datetime.datetime.combine(accrual_start,
                                          datetime.datetime.min.time()),
                'accrual_stop':
                datetime.datetime.combine(accrual_stop,
                                          datetime.datetime.min.time()),
                'nextcall':
                nextcall,
                'sufficient_seniority':
                seniority.date() <= today
            })
        return results