Exemplo n.º 1
0
void BudgetBalancer::processItem(LedgerBudget const& budget)
{
   // if there is a budget period, process recorded items until we are within
   // range of this budget command
   advancePeriodToDate(budget.date());

   // if the current period started before today, or if it already has recorded
   // commands, then end the period today and process what we have
   if (m_period.startDate() != budget.date() || m_numRecords != 0)
   {
      m_period = DateRange(m_period.startDate(), budget.date());
      allocateCategories();
      processRecords();
   }

   // remove categories that are not in this budget command, or that have
   // changed, and allocate their funds to the available category
   auto categories = budget.categories();
   for (auto it = m_categories.cbegin(); it != m_categories.cend(); ++it)
   {
      if (!categories.contains(it.key()) ||
          categories[it.key()].type != it->type)
      {
         switch (it->type)
         {
            case LedgerBudget::Category::Type::GOAL:
               // nothing to do for goals
               break;
            case LedgerBudget::Category::Type::INCOME:
               // nothing to do for income type
               break;
            case LedgerBudget::Category::Type::RESERVE_AMOUNT:
            {
               Currency amount = m_reserveAmountAllocator.deallocate(it.key());
               if (!amount.isZero())
               {
                  emit message(budget,
                               QString("Reserve category '%1' was closed with "
                                       "a balance of %2.  Those funds are "
                                       "available again.")
                               .arg(it.key())
                               .arg(amount.toString()));
               }
               m_available += amount;
               break;
            }
            case LedgerBudget::Category::Type::RESERVE_PERCENT:
            {
               Currency amount = m_reservePercentAllocator.deallocate(it.key());
               if (!amount.isZero())
               {
                  emit message(budget,
                               QString("Reserve category '%1' was closed with "
                                       "a balance of %2.  Those funds are "
                                       "available again.")
                               .arg(it.key())
                               .arg(amount.toString()));
               }
               m_available += amount;
               break;
            }
            case LedgerBudget::Category::Type::ROUTINE:
               m_routineAllocator.deallocate(it.key());
               break;
         }
      }
   }

   // configure new and changed budget categories
   for (auto it = categories.cbegin(); it != categories.cend(); ++it)
   {
      switch (it->type)
      {
         case LedgerBudget::Category::Type::GOAL:
            m_goalAllocator.budget(budget.date());
            break;
         case LedgerBudget::Category::Type::INCOME:
            // nothing to do for income
            break;
         case LedgerBudget::Category::Type::RESERVE_AMOUNT:
            m_reserveAmountAllocator.budget(budget.date(), it.key(), it->amount,
                                            it->interval);
            break;
         case LedgerBudget::Category::Type::RESERVE_PERCENT:
            m_reservePercentAllocator.budget(it.key(), it->percentage);
            break;
         case LedgerBudget::Category::Type::ROUTINE:
            // nothing to do for routine expenses
            break;
      }
   }
   m_categories = categories;

   // reset the dates for the new period
   m_period = DateRange(budget.date(), budget.interval());
}