docs: def createGenericExpenseItems(request=None, datetimeTuple=None, rule=None):
      '''
      Generic repeated expenses are created by just entering an
      expense at each exact point specified by the rule, without
      regard for whether events are scheduled in the specified
      window,
      '''
  
      # These are used repeatedly, so they are put at the top
      submissionUser = getattr(request, 'user', None)
  
      # Return the number of new expense items created
      generate_count = 0
  
      # First, construct the set of rules that need to be checked for affiliated events
      rule_filters = Q(disabled=False) & Q(rentalRate__gt=0) & \
          Q(genericrepeatedexpense__isnull=False)
      if rule:
          rule_filters = rule_filters & Q(id=rule.id)
      rulesToCheck = RepeatedExpenseRule.objects.filter(rule_filters).distinct()
  
      # These are the filters place on Events that overlap the window in which
      # expenses are being generated.
      if datetimeTuple and len(datetimeTuple) == 2:
          timelist = list(datetimeTuple)
          timelist.sort()
      else:
          timelist = None
  
      # Now, we loop through the set of rules that need to be applied, check for an
      # existing expense item at each point specified by the rule, and create a new
      # expense if one does not exist.
      for rule in rulesToCheck:
  
          limits = timelist or [ensure_timezone(datetime.min), ensure_timezone(datetime.max)]
  
          if rule.advanceDays:
              limits[1] = min(limits[1], timezone.now() + timedelta(days=rule.advanceDays))
          if rule.priorDays:
              limits[0] = max(limits[0], timezone.now() - timedelta(days=rule.priorDays))
  
          if rule.startDate:
              limits[0] = max(
                  limits[0],
                  timezone.now().replace(
                      year=rule.startDate.year, month=rule.startDate.month, day=rule.startDate.day,
                      hour=0, minute=0, second=0, microsecond=0,
                  )
              )
          if rule.endDate:
              limits[1] = min(
                  limits[1],
                  timezone.now().replace(
                      year=rule.endDate.year, month=rule.endDate.month, day=rule.endDate.day,
                      hour=0, minute=0, second=0, microsecond=0,
                  )
              )
  
          # Find the first start time greater than the lower bound time.
          if rule.applyRateRule == RepeatedExpenseRule.RateRuleChoices.hourly:
              this_time = limits[0].replace(minute=0, second=0, microsecond=0)
              if this_time < limits[0]:
                  this_time += timedelta(hours=1)
          elif rule.applyRateRule == RepeatedExpenseRule.RateRuleChoices.daily:
              this_time = limits[0].replace(hour=rule.dayStarts, minute=0, second=0, microsecond=0)
              if this_time < limits[0]:
                  this_time += timedelta(days=1)
          elif rule.applyRateRule == RepeatedExpenseRule.RateRuleChoices.weekly:
              offset = limits[0].weekday() - rule.weekStarts
              this_time = limits[0].replace(
                  day=limits[0].day - offset, hour=rule.dayStarts, minute=0, second=0, microsecond=0
              )
              if this_time < limits[0]:
                  this_time += timedelta(days=7)
          else:
              this_time = limits[0].replace(
                  day=rule.monthStarts, hour=rule.dayStarts, minute=0, second=0, microsecond=0
              )
              if this_time < limits[0]:
                  this_time += relativedelta(months=1)
  
          while this_time <= limits[1]:
              defaults_dict = {
                  'category': rule.category,
                  'description': rule.name,
                  'submissionUser': submissionUser,
                  'total': rule.rentalRate,
                  'accrualDate': this_time,
                  'payTo': rule.payTo,
              }
              item, created = ExpenseItem.objects.get_or_create(
                  expenseRule=rule,
                  periodStart=this_time,
                  periodEnd=this_time,
                  defaults=defaults_dict
              )
              if created:
                  generate_count += 1
              if rule.applyRateRule == RepeatedExpenseRule.RateRuleChoices.hourly:
                  this_time += timedelta(hours=1)
              elif rule.applyRateRule == RepeatedExpenseRule.RateRuleChoices.daily:
                  this_time += timedelta(days=1)
              elif rule.applyRateRule == RepeatedExpenseRule.RateRuleChoices.weekly:
                  this_time += timedelta(days=7)
              else:
                  this_time += relativedelta(months=1)
      rulesToCheck.update(lastRun=timezone.now())
      return generate_count