Extends ChildAccount
to model low-level accounts such as bills,
loans, and targeted savings. Adds time-based logic, due tracking, and
automatic closure/reactivation to ensure intelligent fund allocation.
Details
This class introduces behavior tailored to two main categories:
1. Periodic Accounts (e.g., Bills, Rent, Fixed Savings):
Require recurring payments before a
due_date
.If fully funded before the due date, the account is marked
"inactive"
and any surplus is returned to the parent.Upon reaching the next due date, the account reactivates and begins tracking the next cycle's funding needs.
2. Open-Ended Accounts (e.g., Long-Term Debts, Target Savings):
Do not rely on
due_date
or cycles.Once the
fixed_amount
target is met, the account is permanently closed and surplus funds are redirected.This prevents over-allocation to already satisfied targets.
These behaviors:
Guard against poor user allocation strategies by reallocating excess funds from fully funded accounts.
Adapt automatically to variable incomes, ensuring flexible prioritization (e.g., for freelancers).
Allow non-expert users to benefit from dynamic, self-adjusting savings and debt repayment logic over time.
Methods
initialize(...)
Constructor. Sets allocation, type, due date, fixed target, etc.
deposit(...)
Handles reactivation on due date and closes account when target met. Returns surplus to parent account for redistribution.
withdraw(...)
Withdraws funds and adjusts period tracking accordingly.
get_/set_
methodsGet/set values for due date, amount, account type, freq, periods.
Super classes
finman::MainAccount
-> finman::ChildAccount
-> GrandchildAccount
Public fields
status
Character. "active", "inactive", or "closed".
due_date
POSIXct or NULL. When funding is due (for bills, etc.).
amount_due
Numeric. Amount left to fully fund the account.
fixed_amount
Numeric. Fixed target for each funding cycle.
account_type
Character. e.g., "Bill", "Debt", "FixedSaving".
freq
Numeric or NULL. Cycle length in days (for recurring accounts).
num_periods
Numeric. Number of unpaid cycles.
Track_dues_and_balance
Data frame. History of balance and dues.
Methods
Inherited methods
finman::MainAccount$add_child_account()
finman::MainAccount$allocated_amount()
finman::MainAccount$compute_total_balance()
finman::MainAccount$compute_total_due()
finman::MainAccount$compute_total_due_within_n_days()
finman::MainAccount$distribute_to_children()
finman::MainAccount$find_account()
finman::MainAccount$find_account_by_uuid()
finman::MainAccount$generate_transaction_id()
finman::MainAccount$get_balance()
finman::MainAccount$get_transactions()
finman::MainAccount$income_utilization()
finman::MainAccount$is_duplicate_transaction()
finman::MainAccount$list_all_accounts()
finman::MainAccount$list_child_accounts()
finman::MainAccount$move_balance()
finman::MainAccount$set_child_allocation()
finman::MainAccount$spending()
finman::MainAccount$total_income()
finman::MainAccount$walking_amount()
finman::ChildAccount$change_status()
finman::ChildAccount$get_account_status()
finman::ChildAccount$get_priority()
finman::ChildAccount$set_priority()
Method new()
Initializes a new GrandchildAccount
instance with attributes and
tracking suitable for both periodic (e.g., bills, rent, fixed savings)
and open-ended (e.g., long-term debts, target savings) accounts.
Inherits from ChildAccount
and sets up account-specific
parameters like due dates, target amounts, and funding cycles.
Usage
GrandchildAccount$new(
name,
allocation = 0,
priority = 0,
fixed_amount = 0,
due_date = NULL,
account_type = "Expense",
freq = NULL,
status = "active"
)
Arguments
name
Character. Name or label of the account (e.g., "Rent", "Car Loan").
allocation
Numeric. Proportion of parent funds to allocate to this account. Used during distribution logic. Defaults to 0.
priority
Numeric. Priority weight for redistribution of residual funds, especially in cases of overflow or unmet allocations. Defaults to 0.
fixed_amount
Numeric. Target amount required to fully fund the account per period or in total. Used for both bills and savings goals.
due_date
POSIXct or NULL. Optional due date indicating when the next funding cycle is expected (for recurring accounts).
account_type
Character. Type of the account: e.g., "Bill", "Debt", "FixedSaving", or "Expense". Influences reactivation and closure behavior. Defaults to "Expense".
freq
Numeric or NULL. Frequency in days for periodic accounts to recur. Required for automated reactivation logic.
status
Character. "active", "inactive", or "closed".
Details
The constructor also initializes a data frame
Track_dues_and_balance
to monitor the account's funding status over time. Each row logs
the current due amount and balance upon deposit or withdrawal.
For accounts of type "Bill", "FixedSaving", or "Debt"
(with a due_date
), the constructor sets up fields that support
automated activation, deactivation, and fund tracking per cycle.
Examples
# Initialize a rent account due every 30 days with a fixed monthly cost
library(R6)
library(uuid)
library(tidyverse)
rent <- GrandchildAccount$new(
name = "Rent",
allocation = 0.3,
priority = 2,
fixed_amount = 75000,
due_date = Sys.Date() + 30,
account_type = "Bill",
freq = 30
)
# Initialize a target savings account without a due date
car_saving <- GrandchildAccount$new(
name = "Car Fund",
allocation = 0.2,
fixed_amount = 500000,
account_type = "FixedSaving"
)
Method get_due_date()
Retrieves the current due date of the account. This is typically used for periodic accounts such as bills or fixed savings that require funding on a recurring schedule.
Examples
rent <- GrandchildAccount$new(
name = "Rent",
fixed_amount = 75000,
due_date = Sys.Date() + 30
)
rent$get_due_date()
Method set_due_date()
Sets a new due date for the account. This is useful for accounts with periodic funding requirements, such as rent, bills, or fixed savings.
Examples
bill <- GrandchildAccount$new(name = "Electricity", fixed_amount = 5000)
bill$set_due_date(Sys.Date() + 15)
Method get_fixed_amount()
Retrieves the fixed amount assigned to the account. This is typically used in accounts like bills, fixed savings, or loan payments where a specific amount is expected periodically.
Examples
rent <- GrandchildAccount$new(name = "Rent", fixed_amount = 75000)
rent$get_fixed_amount()
#> [1] 75000
Method set_fixed_amount()
Sets a new fixed amount for the account. This value represents the expected periodic contribution or payment (e.g., monthly rent, loan installment). It also recalculates the current amount due based on the number of unpaid periods and the account balance.
Examples
rent <- GrandchildAccount$new(name = "Rent", fixed_amount = 50000)
rent$set_fixed_amount(75000)
#> Fixed amount for Rent set to 75000
Method get_account_type()
Sets a new fixed amount for the account. This value represents the expected periodic contribution or payment (e.g., monthly rent, loan installment). It also recalculates the current amount due based on the number of unpaid periods and the account balance.
Examples
rent <- GrandchildAccount$new(name = "Rent", fixed_amount = 50000)
rent$set_fixed_amount(75000)
#> Fixed amount for Rent set to 75000
Method set_account_type()
Sets the type of the account, which influences how it behaves with respect to funding, reactivation, and closure policies. This field is central to determining whether the account is recurring, fixed, or target-based.
Arguments
account_type
Character. One of the supported types such as
"Bill"
,"Debt"
,"FixedSaving"
,"NonFixedSaving"
, or"Expense"
. Determines how due dates, funding limits, and surplus reallocation are handled.
Details
- "Bill"
or "FixedSaving"
: These accounts are period-based
and are reactivated upon due dates.
- "Debt"
or target savings: Once fully funded, they are closed and
not reopened.
- "Expense"
or "NonFixedSaving"
: Do not enforce due dates
or strict funding targets.
Examples
rent <- GrandchildAccount$new(name = "Rent", fixed_amount = 75000)
rent$set_account_type("Bill")
#> Account type for Rent set to Bill
Method deposit()
Handles incoming deposits for grandchild accounts, including complex behavior for fixed-amount accounts such as Bills, FixedSavings, and Debts. It intelligently manages due dates, period increments, surplus reallocation, and account status updates.
Usage
GrandchildAccount$deposit(
amount,
transaction_number = NULL,
by = "User",
channel = NULL,
date = Sys.time()
)
Arguments
amount
Numeric. The amount of money being deposited into the account.
transaction_number
Character or NULL. Optional unique identifier for the transaction. If NULL, a new one is generated.
by
Character. The party initiating the transaction (default is "User").
channel
Character or NULL. The method or channel used for the transaction (e.g., "Mobile Money").
date
POSIXct. The timestamp for the transaction (defaults to current system time).
Details
This method supports two core behaviors depending on the type of account:
## 1. Period-based Accounts (`Bill`, `FixedSaving`) - If the due date has passed, the system automatically increments the number of unpaid periods and extends the due date. - If the deposited amount fully covers the required amount across all unpaid periods, the account is marked as `"inactive"` (temporarily closed). - Any surplus is redirected to the parent account for reallocation, ensuring no money is trapped in overfunded accounts. - The transaction is logged in `Track_dues_and_balance` to track financial health over time.
## 2. Non-period Accounts (`LongTermDebt`, `TargetSaving`) - When the required amount is met, the account is permanently closed, and will not reactivate. This design ensures funds are focused on accounts that still need attention.
This mechanism encourages automatic reallocation of excess funds to critical needs without requiring users to micromanage their allocations — useful especially for users with fluctuating income.
Examples
# main account
main<- MainAccount$new("main")
# child account
child <- ChildAccount$new(
name = "Emergency Fund",
allocation = 0.3,
priority = 2
)
# Grand child account
bill <- GrandchildAccount$new(
name = "Rent",
fixed_amount = 75000,
account_type = "Bill",
due_date = Sys.Date(),
freq = 30
)
# attach grand child to parent
main$add_child_account(child)
child$add_child_account(bill)
bill$deposit(75000,channel="ABSA")
# Example with surplus being returned to parent:
bill$deposit(80000,channel="ABSA")
# Example with underpayment:
bill$deposit(20000,channel="ABSA") # Remains active, shows updated due
Method withdraw()
Handles withdrawal requests from a grandchild account. The method ensures sufficient balance is available, updates the internal transaction tracking, and compensates for partial withdrawals in fixed-amount accounts by adjusting the effective number of periods.
Usage
GrandchildAccount$withdraw(
amount,
transaction_number = NULL,
by = "User",
channel = NULL,
date = Sys.time()
)
Arguments
amount
Numeric. The amount to withdraw from the account.
transaction_number
Character or NULL. Optional transaction reference ID.
by
Character. The party initiating the withdrawal (default is "User").
channel
Character or NULL. Source or medium of the transaction (e.g., "Mobile Money").
date
POSIXct. The date and time of withdrawal (default is current system time).
Details
The method performs the following steps:
- Checks whether the account balance is sufficient for the requested withdrawal. - If sufficient, it processes the withdrawal via the parent class method. - It then logs the updated balance and remaining amount due into the `Track_dues_and_balance` history.
For accounts with a `fixed_amount` (e.g., Bills, FixedSavings, Debts):
- Partial withdrawals are treated as funding reversals and reduce the number of fulfilled periods. - This ensures that the system maintains accurate state about what's left to fulfill for the account, without modifying the `fixed_amount` itself.
This mechanism is crucial in dynamic environments where users may occasionally retrieve money from priority accounts — e.g., for emergencies — and helps the system readjust allocation logic accordingly.
Examples
# Withdraw a partial amount from a fully funded rent account
rent <- GrandchildAccount$new("Rent", fixed_amount = 75000,
account_type = "Bill")
rent$deposit(75000,channel="ABSA")
# Now equivalent to 0.53 of the rent period remaining.
rent$withdraw(35000,channel="ABSA")
Method get_account_freq()
Retrieves the recurrence frequency of the account, typically used for accounts with periodic obligations such as bills, fixed savings, or loans.
Details
This frequency determines how often the account expects funding. For instance, a rent account with a monthly cycle would have a frequency of 30 (days), while a weekly expense might have 7.
This field is primarily used in due date updates and period tracking, especially for auto-reactivating accounts like Bills or Fixed Savings after their due dates lapse.
Returns
The frequency of recurrence, as stored in the account (e.g., number of days, or a character label like "monthly").
Examples
acc <- GrandchildAccount$new(
"Rent",
fixed_amount = 1000,
freq = 30
)
acc$get_account_freq()
# [1] 30
Method set_account_freq()
Sets the recurrence frequency of the account, which defines how often the account expects to be funded.
Arguments
account_freq
Numeric or character value representing the recurrence frequency. For example, use `30` for a monthly bill or `"weekly"` if implementing a custom handler.
Details
This frequency value is crucial for managing due dates and determining when a new period starts (e.g., when a rent account should reactivate after a month).It is used in conjunction with the due date to trigger reactivation and allocation adjustments for fixed-type accounts such as Bills, Fixed Savings, and Loans. Changing the frequency may affect how missed or overdue periods are computed going forward.
Examples
acc <- GrandchildAccount$new("Water Bill", fixed_amount = 500)
acc$set_account_freq(30)
# Frequency for Water Bill set to 30
Method get_account_periods()
Retrieves the number of unpaid or active periods associated with the account.
Details
This is particularly relevant for fixed-type accounts like Bills, Fixed Savings, or Debts with a defined frequency. The number of periods (`num_periods`) represents how many cycles have passed without full funding. It increases when due dates pass without adequate deposits and decreases when partial withdrawals are made from already-funded periods.
For example, if a rent account expects funding every 30 days and misses two cycles, `num_periods` will be 3 (including the current one), and the system will attempt to fund all missed cycles.
Examples
acc <- GrandchildAccount$new(
"Internet Bill",
fixed_amount = 2500,
freq = 30
)
acc$get_account_periods()
# [1] 1
Method set_account_periods()
Manually sets the number of unpaid or active periods for the account.
Details
This method allows manual control of how many cycles (e.g., months or days) are currently due or tracked for the account. It can be used in administrative corrections or simulations of time passage in budgeting models.
Use with caution: setting `num_periods` directly may desynchronize with the actual due date logic unless adjustments are consistently maintained.
Examples
acc <- GrandchildAccount$new("Loan Payment", fixed_amount = 10000,
freq = 30)
acc$set_account_periods(3)
# Output: Loan Payment has 3 period(s)
Examples
## ------------------------------------------------
## Method `GrandchildAccount$new`
## ------------------------------------------------
# Initialize a rent account due every 30 days with a fixed monthly cost
library(R6)
library(uuid)
library(tidyverse)
rent <- GrandchildAccount$new(
name = "Rent",
allocation = 0.3,
priority = 2,
fixed_amount = 75000,
due_date = Sys.Date() + 30,
account_type = "Bill",
freq = 30
)
# Initialize a target savings account without a due date
car_saving <- GrandchildAccount$new(
name = "Car Fund",
allocation = 0.2,
fixed_amount = 500000,
account_type = "FixedSaving"
)
## ------------------------------------------------
## Method `GrandchildAccount$get_due_date`
## ------------------------------------------------
rent <- GrandchildAccount$new(
name = "Rent",
fixed_amount = 75000,
due_date = Sys.Date() + 30
)
rent$get_due_date()
#> [1] "2025-08-31"
## ------------------------------------------------
## Method `GrandchildAccount$set_due_date`
## ------------------------------------------------
bill <- GrandchildAccount$new(name = "Electricity", fixed_amount = 5000)
bill$set_due_date(Sys.Date() + 15)
#> Due date for Electricity set to 20316
## ------------------------------------------------
## Method `GrandchildAccount$get_fixed_amount`
## ------------------------------------------------
rent <- GrandchildAccount$new(name = "Rent", fixed_amount = 75000)
rent$get_fixed_amount()
#> [1] 75000
#> [1] 75000
## ------------------------------------------------
## Method `GrandchildAccount$set_fixed_amount`
## ------------------------------------------------
rent <- GrandchildAccount$new(name = "Rent", fixed_amount = 50000)
rent$set_fixed_amount(75000)
#> Fixed amount for Rent set to 75000
#> Fixed amount for Rent set to 75000
## ------------------------------------------------
## Method `GrandchildAccount$get_account_type`
## ------------------------------------------------
rent <- GrandchildAccount$new(name = "Rent", fixed_amount = 50000)
rent$set_fixed_amount(75000)
#> Fixed amount for Rent set to 75000
#> Fixed amount for Rent set to 75000
## ------------------------------------------------
## Method `GrandchildAccount$set_account_type`
## ------------------------------------------------
rent <- GrandchildAccount$new(name = "Rent", fixed_amount = 75000)
rent$set_account_type("Bill")
#> Account type for Rent set to Bill
#> Account type for Rent set to Bill
## ------------------------------------------------
## Method `GrandchildAccount$deposit`
## ------------------------------------------------
# main account
main<- MainAccount$new("main")
# child account
child <- ChildAccount$new(
name = "Emergency Fund",
allocation = 0.3,
priority = 2
)
# Grand child account
bill <- GrandchildAccount$new(
name = "Rent",
fixed_amount = 75000,
account_type = "Bill",
due_date = Sys.Date(),
freq = 30
)
# attach grand child to parent
main$add_child_account(child)
child$add_child_account(bill)
bill$deposit(75000,channel="ABSA")
#> Due date extended. Number of periods unpaid: 2
#> Rent reactivated. Outstanding balance due: 150000
#> Deposited: 75000 via ABSA - Transaction ID: sys1
# Example with surplus being returned to parent:
bill$deposit(80000,channel="ABSA")
#> Deposited: 75000 via ABSA - Transaction ID: sys2
#> Rent has become inactive .
#> Extra amount of 5000 moved to Emergency Fund
#> Rent fully funded for 2 period(s)
# Example with underpayment:
bill$deposit(20000,channel="ABSA") # Remains active, shows updated due
#> Deposit not allowed. Account is not active.
#> Rent has become inactive .
#> Extra amount of 20000 moved to Emergency Fund
#> Rent fully funded for 2 period(s)
## ------------------------------------------------
## Method `GrandchildAccount$withdraw`
## ------------------------------------------------
# Withdraw a partial amount from a fully funded rent account
rent <- GrandchildAccount$new("Rent", fixed_amount = 75000,
account_type = "Bill")
rent$deposit(75000,channel="ABSA")
#> Deposited: 75000 via ABSA - Transaction ID: sys1
#> Rent has become inactive .
#> Rent fully funded for 1 period(s)
# Now equivalent to 0.53 of the rent period remaining.
rent$withdraw(35000,channel="ABSA")
#> Withdrew: 35000 via ABSA - Transaction ID: sys2
## ------------------------------------------------
## Method `GrandchildAccount$get_account_freq`
## ------------------------------------------------
acc <- GrandchildAccount$new(
"Rent",
fixed_amount = 1000,
freq = 30
)
acc$get_account_freq()
#> [1] 30
# [1] 30
## ------------------------------------------------
## Method `GrandchildAccount$set_account_freq`
## ------------------------------------------------
acc <- GrandchildAccount$new("Water Bill", fixed_amount = 500)
acc$set_account_freq(30)
#> Frequency for Water Bill set to 30
# Frequency for Water Bill set to 30
## ------------------------------------------------
## Method `GrandchildAccount$get_account_periods`
## ------------------------------------------------
acc <- GrandchildAccount$new(
"Internet Bill",
fixed_amount = 2500,
freq = 30
)
acc$get_account_periods()
#> [1] 1
# [1] 1
## ------------------------------------------------
## Method `GrandchildAccount$set_account_periods`
## ------------------------------------------------
acc <- GrandchildAccount$new("Loan Payment", fixed_amount = 10000,
freq = 30)
acc$set_account_periods(3)
#> Loan Payment has 3 period(s)
# Output: Loan Payment has 3 period(s)