The `MainAccount` R6 class represents the top-level virtual account in a hierarchical financial structure. It receives all income and is responsible for distributing funds to its child accounts based on allocation rules.
This class is the core of the budgeting engine and manages:
Income reception and logging.
Transaction tracking via a structured data frame.
A list of linked child accounts.
Auto-generated UUID for identification.
A balance that reflects both manual and system transactions.
Details
The account includes the following core attributes:
- uuid
A unique identifier for the account, auto-generated.
- name
Human-readable name for the account.
- balance
Current balance in the account.
- transactions
A `data.frame` tracking transaction logs, including custom system transactions.
- transaction_counter
Used internally to create unique transaction IDs.
- child_accounts
A list containing attached child accounts.
- total_allocation
Tracks the total allocation distributed to children.
- path
Logical traversal path from the root (used to locate accounts hierarchically).
Hierarchy
This is the top-level class in a hierarchy that includes:
MainAccount: Root of the virtual budget system.
ChildAccount: Draws a portion of income from the MainAccount.
GrandChildAccount: Represents specific budget goals (e.g., rent, savings) and has due dates, frequency, and priority logic.
Public fields
uuid
Auto-generated unique identifier.
name
Account name.
balance
Current balance.
transactions
A `data.frame` of transaction logs.
transaction_counter
Counter used to generate unique transaction IDs.
child_accounts
List of child accounts.
total_allocation
Numeric. Sum of allocated funds to children.
path
Character vector representing the account's hierarchy path.
# some imports
Methods
Method new()
Constructor for the `MainAccount` class. Initializes a new main account with a unique identifier, user-defined name, zero balance, and an empty transaction data frame. Also sets the default account path to "main_account".
Usage
MainAccount$new(name, balance = 0)
Method generate_transaction_id()
Generates a unique system transaction ID by appending an incrementing counter to a fixed prefix ("sys"). The counter is then incremented for future calls.
Method is_duplicate_transaction()
Checks if a given transaction number already exists in the transaction log. This is used to prevent duplicate transaction entries.
Examples
\dontrun{
# Create a new main account
main_acc <- MainAccount$new(name = "Salary Pool")
# Manually add a transaction with ID "sys1"
main_acc$transactions <- data.frame(
Type = "Income",
By = "User",
TransactionID = "sys1",
Channel = "Bank",
Amount = 5000,
Balance = 5000,
amount_due = 0,
overall_balance = 5000,
Date = Sys.time(),
stringsAsFactors = FALSE
)
# Check for duplicate
main_acc$is_duplicate_transaction("sys1") # Returns TRUE
main_acc$is_duplicate_transaction("sys2") # Returns FALSE
}
Method deposit()
Deposits a specified amount into the account and distributes it to child accounts based on allocation rules. This method also records the transaction in the internal ledger.
Usage
MainAccount$deposit(
amount,
transaction_number = NULL,
by = "User",
channel = NULL,
date = Sys.time()
)
Arguments
amount
Numeric. The amount of money to deposit. Must be greater than zero.
transaction_number
Optional character. A unique identifier for this transaction. If not provided, the system generates one automatically.
by
Character. Identifier of the depositor (default is `"User"`).
channel
Character. The source of funds (e.g., `"ABSA"`, `"MPESA"`). Required.
date
POSIXct or character. The timestamp of the transaction (defaults to current time).
Method distribute_to_children()
Distributes a given amount from the an account to active child accounts based on their allocation weights and priorities. If the amount is too small (less than 0.10), it is routed entirely to the highest-priority child.
This method is automatically called after a deposit into a parent account. It performs internal withdrawals and instructs child accounts to deposit their corresponding shares.
Arguments
amount
Numeric. Total amount available for distribution.
transaction
Character. The transaction ID associated with the distribution.
by
Character. Identifier of the actor performing the transfer (default is `"System"`).
Returns
No return value. This method updates balances and transaction logs in both the main account and all affected child accounts.
Examples
\dontrun{
main_acc <- MainAccount$new(name = "Salary Pool")
child1 <- ChildAccount$new(name = "Food Fund", allocation = 0.6)
child2 <- ChildAccount$new(name = "Savings", allocation = 0.4)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
main_acc$deposit(amount = 1000, channel = "Bank")
# This will trigger distribute_to_children internally.
}
Method add_child_account()
Adds a `ChildAccount` object to the list of child accounts of the account. It checks for valid allocation percentages (must not exceed 100 hierarchical path references, and updates total allocation.
Arguments
child_account
An object of class `ChildAccount`or `GrandChildAccount`, representing the account to be added as a subordinate of the current main account.
Method set_child_allocation()
Updates the allocation percentage for a specified child account. Ensures that the total allocation across all children does not exceed 100
Arguments
child_account_name
Character. The name of the child account whose allocation is to be updated.
new_allocation
Numeric. The new allocation proportion (between 0 and 1).
Method withdraw()
Withdraws a specified amount from the account and logs the transaction. A transaction number is generated automatically if not provided. Withdrawals require a valid channel and sufficient balance.
Usage
MainAccount$withdraw(
amount,
transaction_number = NULL,
by = "User",
channel = NULL,
date = Sys.time()
)
Arguments
amount
Numeric. The amount to withdraw. Must be greater than zero and #' not exceed the current balance.
transaction_number
Optional character. Custom transaction ID. If NULL, a system-generated ID will be used.
by
Character. The entity initiating the withdrawal. Default is `"User"`.
channel
Character. The withdrawal channel (e.g., "Bank Transfer"). Required.
date
POSIXct. Timestamp for the transaction. Defaults to `Sys.time()`.
Method get_transactions()
Retrieves and displays the transaction history for the account. If no transactions are found, a message is printed. Otherwise, the transaction log is displayed in the console.
This method is inherited by child and grandchild account classes.
Method list_child_accounts()
Lists all direct child accounts attached to this account. If no child accounts are found, a message is printed.
This method is inherited by both `ChildAccount` and `GrandChildAccount`, allowing recursive visibility into nested account structures.
Method find_account()
Recursively searches the current account, its children, and its parent chain to collect **all** accounts with a given name. This version differs from the original by not stopping at the first match—it returns a list of **all** matches instead.
It avoids infinite recursion by tracking visited account paths.
Arguments
target_name
Character. The name of the account(s) to locate.
visited_paths
(Internal use only) Tracks visited paths to avoid cycles.
matches
(Internal use only) A list to accumulate matches during recursion.
Returns
A list of account objects matching the given name. If no matches are found, returns an empty list.
Examples
\dontrun{
main <- MainAccount$new("Main")
savings1 <- ChildAccount$new("Savings", allocation = 0.5)
savings2 <- ChildAccount$new("Savings", allocation = 0.3)
main$add_child_account(savings1)
main$add_child_account(savings2)
found <- main$find_account("Savings")
length(found) # 2
found[[1]]$uuid
}
Method find_account_by_uuid()
Recursively searches for an account by its unique UUID. The method traverses downward through all child accounts and upward to the parent, if needed, while preventing circular recursion by tracking visited paths. This is especially useful when account names are not unique but UUIDs are.
Arguments
target_uuid
Character. The UUID of the account to find.
visited_paths
Internal use only. A list used to track visited paths and prevent infinite loops in cyclic or nested account structures.
Examples
\dontrun{
main_acc <- MainAccount$new("Root")
groceries <- ChildAccount$new("Groceries", allocation = 0.3)
main_acc$add_child_account(groceries)
found <- main_acc$find_account_by_uuid(groceries$uuid)
if (!is.null(found)) cat("Found UUID:", found$uuid)
}
# Move balance to another account (by UUID)
Method move_balance()
Moves a specified amount from the current account to another account identified by its **UUID**. This is intended for internal transfers within the account tree. It reuses `withdraw()` and `deposit()` logic and logs the transfer using the "Internal Transfer" channel.
The target account is resolved using `find_account_by_uuid()`, not by name. This ensures unambiguous targeting even when accounts share the same name.
Arguments
target_account_uuid
Character. The UUID of the account to which the funds will be moved.
amount
Numeric. The amount to transfer. Must be less than or equal to the current account's balance.
Returns
No return value. Side effects include balance updates and transaction logs for both the source and target accounts.
Examples
\dontrun{
main_acc <- MainAccount$new("Main")
savings <- ChildAccount$new("Savings", allocation = 0.5)
emergency <- ChildAccount$new("Emergency", allocation = 0.5)
main_acc$add_child_account(savings)
main_acc$add_child_account(emergency)
# Initial deposit
main_acc$deposit(1000, channel = "Bank")
# Move 200 to savings using UUID
main_acc$move_balance(savings$uuid, 200)
}
Method list_all_accounts()
Recursively lists the names of all accounts in the hierarchy, both upward (towards ancestors) and downward (towards descendants), starting from the current account. This method avoids revisiting any account by tracking visited paths, preventing infinite loops in case of circular references.
Arguments
visited_paths
Optional list. Used internally for recursion to avoid revisiting accounts. Should generally be left as `NULL` by the user.
Returns
A character vector of account names found across the full reachable tree (both children and ancestors) from the current account.
Examples
\dontrun{
main_acc <- MainAccount$new("Main")
savings <- ChildAccount$new("Savings", allocation = 0.4)
emergency <- ChildAccount$new("Emergency", allocation = 0.6)
main_acc$add_child_account(savings)
main_acc$add_child_account(emergency)
# List all accounts from the root
main_acc$list_all_accounts()
# Output: "Main" "Savings" "Emergency"
# List all accounts from a child node (will include parents)
savings$list_all_accounts()
# Output: "Savings" "Main" "Emergency"
}
Method compute_total_balance()
Recursively computes the total balance held by the current account and all of its child accounts. This method includes the balance of the account on which it's called and traverses down the tree to sum balances of all active descendants.
Examples
\dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.5)
child2 <- ChildAccount$new("Child2", allocation = 0.5)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
main_acc$deposit(100, channel = "Bank", transaction_number = "txn1")
# This distributes 100 into child1 and child2 based on allocation
# Check total balance recursively
total <- main_acc$compute_total_balance()
print(total)
# Should return 100 (main + children)
}
Method compute_total_due()
Recursively computes the total amount due for the current account and all of its descendant child accounts. If `amount_due` is not defined in an account, it defaults to zero.
This is useful for aggregating outstanding dues across the entire hierarchical account structure (e.g., main → child → grandchild).
Examples
\dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.6)
child2 <- ChildAccount$new("Child2", allocation = 0.4)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
# Manually set dues
main_acc$amount_due <- 50
child1$amount_due <- 20
child2$amount_due <- 30
total_due <- main_acc$compute_total_due()
print(total_due)
# Should return 100 (50 + 20 + 30)
}
Method compute_total_due_within_n_days()
Recursively computes the total amount due for the current account and all
child accounts where the due date is within the next n
days from
the current system time.
This method is useful for identifying upcoming payments or obligations in a multi-account hierarchy and prioritizing them based on urgency.
Arguments
n
Integer. The number of days from today within which dues should be considered. Dues without a due date are ignored.
Examples
\dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.6)
child2 <- ChildAccount$new("Child2", allocation = 0.4)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
# Assign dues and due dates
main_acc$amount_due <- 100
main_acc$due_date <- Sys.time() + 2 * 24 * 60 * 60 # Due in 2 days
child1$amount_due <- 50
child1$due_date <- Sys.time() + 5 * 24 * 60 * 60 # Due in 5 days
child2$amount_due <- 70
child2$due_date <- Sys.time() + 10 * 24 * 60 * 60 # Due in 10 days
# Compute total dues within next 7 days
total_due_7_days <- main_acc$compute_total_due_within_n_days(7)
print(total_due_7_days)
# Should return 100 + 50 = 150
}
Method spending()
Recursively computes the total spending (i.e., user-initiated withdrawals) for the current account and all child accounts within a specified date range.
Spending is defined as withdrawals made by the user (`By == "User"`), excluding system-initiated or internal transfers. The function includes both the current account and all of its descendants in the calculation.
Arguments
daterange
A Date or POSIXct vector of length 2. The start and end dates for the period over which to compute spending. Defaults to the entire timeline.
Examples
\dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.5)
child2 <- ChildAccount$new("Child2", allocation = 0.5)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
# Simulate some deposits and withdrawals
main_acc$deposit(500, "T1", By = "User", channel = "Cash")
main_acc$withdraw(200, By = "User", channel = "Spending",
date = Sys.time() - 10)
child1$deposit(300, "T2", By = "User", channel = "Mobile")
child1$withdraw(100, By = "User", channel = "Shopping",
date = Sys.time() - 5)
# Get total user spending in last 30 days
main_acc$spending(c(Sys.Date() - 30, Sys.Date()))
# Should return 200 + 100 = 300
}
Method total_income()
Recursively computes the total income (i.e., user-initiated deposits) for the current account and all of its child accounts within a specified date range.
This function sums up all "Deposit" transactions where the `By` field is set to `"User"`. It includes both the current account and all of its descendants in the income calculation.
Arguments
daterange
A vector of two Dates or POSIXct objects specifying the start and end dates for the income calculation. Defaults to the entire timeline.
Returns
A numeric value representing the total income across all relevant accounts within the specified date range.
Examples
\dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.5)
child2 <- ChildAccount$new("Child2", allocation = 0.5)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
# Simulate some deposits
main_acc$deposit(500, "TX01", By = "User", channel = "Cash",
date = Sys.time() - 7)
child1$deposit(300, "TX02", By = "User", channel = "Mobile",
date = Sys.time() - 3)
# Get total income in last 10 days
main_acc$total_income(c(Sys.Date() - 10, Sys.Date()))
# Should return 500 + 300 = 800
}
Method allocated_amount()
Calculates the total allocated amount to this account and its child accounts over a specified date range.
This includes **all deposits** (from both `"User"` and `"System"`) into the current account, **plus** all **user-initiated** deposits into child and deeper-level descendant accounts. It provides insight into how much funding (regardless of origin) has been allocated directly or indirectly to this node in the account tree.
Arguments
daterange
A vector of two `Date` or `POSIXct` objects specifying the start and end dates for the deposit aggregation. Defaults to a very wide range.
Returns
A numeric value representing the total allocated amount across the account and its descendants within the specified date range.
Examples
\dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.5)
child2 <- ChildAccount$new("Child2", allocation = 0.5)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
main_acc$deposit(1000, "TX001", By = "System", channel = "Bank",
date = Sys.time() - 5)
child1$deposit(300, "TX002", By = "User", channel = "Mobile",
date = Sys.time() - 3)
child2$deposit(200, "TX003", By = "User", channel = "Cash",
date = Sys.time() - 2)
# Get total allocated amount within last 7 days
main_acc$allocated_amount(c(Sys.Date() - 7, Sys.Date()))
# Expected output: 1000 (System) + 300 + 200 = 1500
}
Method income_utilization()
Computes the **income utilization ratio** over a specified date range.
This is calculated as the ratio of total user withdrawals (`spending`) to the total allocated income (`allocated_amount`). It measures how effectively funds are being used relative to the total amount deposited (both by user and system).
A value close to 1 indicates high utilization (most funds spent), while a valueclose to 0 indicates low spending relative to funds received.
Arguments
daterange
A vector of two `Date` or `POSIXct` values defining the date range for the calculation. Defaults to a large historical window.
Method walking_amount()
Computes the **latest recorded amount** (either `amount_due` or `balance`) from the `Track_dues_and_balance` tracker for the current account and all its child accounts within a specified date range.
It retrieves the latest entry in the given date range, and recursively sums the values for all child accounts.
Arguments
amt_type
A string specifying the metric to return: - `"amount_due"`: Return the last tracked `Amount_due`. - `"Balance"`: Return the last tracked `Balance`.
daterange
A vector of two dates (of class `Date` or `POSIXct`) specifying the time window. Default: wide historical range.
Examples
library(R6)
library(uuid)
library(tidyverse)
# Create a main account
acc <- MainAccount$new(name = "Salary Pool", balance = 1000)
# Generate a system transaction ID
acc$generate_transaction_id()
#> [1] "sys1"
# Check for duplicate transaction ID
acc$is_duplicate_transaction("sys1")
#> [1] FALSE
# Inspect balance
acc$balance
#> [1] 1000
# Inspect UUID
acc$uuid
#> [1] "acc3e98c72b-7231-45f7-882c-74d134b0f853"
## ------------------------------------------------
## Method `MainAccount$new`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new(name = "My Main Account")
print(main_acc$uuid)
print(main_acc$balance)
print(main_acc$transactions)
} # }
## ------------------------------------------------
## Method `MainAccount$generate_transaction_id`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new(name = "Salary Pool")
txn_id1 <- main_acc$generate_transaction_id()
txn_id2 <- main_acc$generate_transaction_id()
print(txn_id1) # e.g., "sys1"
print(txn_id2) # e.g., "sys2"
} # }
## ------------------------------------------------
## Method `MainAccount$is_duplicate_transaction`
## ------------------------------------------------
if (FALSE) { # \dontrun{
# Create a new main account
main_acc <- MainAccount$new(name = "Salary Pool")
# Manually add a transaction with ID "sys1"
main_acc$transactions <- data.frame(
Type = "Income",
By = "User",
TransactionID = "sys1",
Channel = "Bank",
Amount = 5000,
Balance = 5000,
amount_due = 0,
overall_balance = 5000,
Date = Sys.time(),
stringsAsFactors = FALSE
)
# Check for duplicate
main_acc$is_duplicate_transaction("sys1") # Returns TRUE
main_acc$is_duplicate_transaction("sys2") # Returns FALSE
} # }
## ------------------------------------------------
## Method `MainAccount$deposit`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new(name = "Salary Pool")
main_acc$deposit(
amount = 1000,
channel = "Bank Transfer"
)
} # }
## ------------------------------------------------
## Method `MainAccount$distribute_to_children`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new(name = "Salary Pool")
child1 <- ChildAccount$new(name = "Food Fund", allocation = 0.6)
child2 <- ChildAccount$new(name = "Savings", allocation = 0.4)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
main_acc$deposit(amount = 1000, channel = "Bank")
# This will trigger distribute_to_children internally.
} # }
## ------------------------------------------------
## Method `MainAccount$add_child_account`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new(name = "Master")
child_acc <- ChildAccount$new(name = "Savings", allocation = 0.4)
main_acc$add_child_account(child_acc)
} # }
## ------------------------------------------------
## Method `MainAccount$set_child_allocation`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Main")
child <- ChildAccount$new(name = "Emergency", allocation = 0.2)
main_acc$add_child_account(child)
main_acc$set_child_allocation("Emergency", 0.3)
} # }
## ------------------------------------------------
## Method `MainAccount$withdraw`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Primary Pool")
main_acc$deposit(amount = 1000, channel = "Mobile", by = "User")
main_acc$withdraw(amount = 200, channel = "ATM", by = "User")
} # }
## ------------------------------------------------
## Method `MainAccount$get_balance`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Primary Pool")
main_acc$deposit(amount = 500, channel = "Bank Transfer")
main_acc$get_balance()
} # }
## ------------------------------------------------
## Method `MainAccount$get_transactions`
## ------------------------------------------------
if (FALSE) { # \dontrun{
acc <- MainAccount$new("Main Budget")
acc$deposit(500, channel = "M-Pesa")
acc$get_transactions()
} # }
## ------------------------------------------------
## Method `MainAccount$list_child_accounts`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Main Budget")
child <- ChildAccount$new("Bills", allocation = 0.5)
main_acc$add_child_account(child)
main_acc$list_child_accounts()
} # }
# Recursively find all accounts by name
## ------------------------------------------------
## Method `MainAccount$find_account`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main <- MainAccount$new("Main")
savings1 <- ChildAccount$new("Savings", allocation = 0.5)
savings2 <- ChildAccount$new("Savings", allocation = 0.3)
main$add_child_account(savings1)
main$add_child_account(savings2)
found <- main$find_account("Savings")
length(found) # 2
found[[1]]$uuid
} # }
## ------------------------------------------------
## Method `MainAccount$find_account_by_uuid`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Root")
groceries <- ChildAccount$new("Groceries", allocation = 0.3)
main_acc$add_child_account(groceries)
found <- main_acc$find_account_by_uuid(groceries$uuid)
if (!is.null(found)) cat("Found UUID:", found$uuid)
} # }
# Move balance to another account (by UUID)
## ------------------------------------------------
## Method `MainAccount$move_balance`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Main")
savings <- ChildAccount$new("Savings", allocation = 0.5)
emergency <- ChildAccount$new("Emergency", allocation = 0.5)
main_acc$add_child_account(savings)
main_acc$add_child_account(emergency)
# Initial deposit
main_acc$deposit(1000, channel = "Bank")
# Move 200 to savings using UUID
main_acc$move_balance(savings$uuid, 200)
} # }
## ------------------------------------------------
## Method `MainAccount$list_all_accounts`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Main")
savings <- ChildAccount$new("Savings", allocation = 0.4)
emergency <- ChildAccount$new("Emergency", allocation = 0.6)
main_acc$add_child_account(savings)
main_acc$add_child_account(emergency)
# List all accounts from the root
main_acc$list_all_accounts()
# Output: "Main" "Savings" "Emergency"
# List all accounts from a child node (will include parents)
savings$list_all_accounts()
# Output: "Savings" "Main" "Emergency"
} # }
## ------------------------------------------------
## Method `MainAccount$compute_total_balance`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.5)
child2 <- ChildAccount$new("Child2", allocation = 0.5)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
main_acc$deposit(100, channel = "Bank", transaction_number = "txn1")
# This distributes 100 into child1 and child2 based on allocation
# Check total balance recursively
total <- main_acc$compute_total_balance()
print(total)
# Should return 100 (main + children)
} # }
## ------------------------------------------------
## Method `MainAccount$compute_total_due`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.6)
child2 <- ChildAccount$new("Child2", allocation = 0.4)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
# Manually set dues
main_acc$amount_due <- 50
child1$amount_due <- 20
child2$amount_due <- 30
total_due <- main_acc$compute_total_due()
print(total_due)
# Should return 100 (50 + 20 + 30)
} # }
## ------------------------------------------------
## Method `MainAccount$compute_total_due_within_n_days`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.6)
child2 <- ChildAccount$new("Child2", allocation = 0.4)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
# Assign dues and due dates
main_acc$amount_due <- 100
main_acc$due_date <- Sys.time() + 2 * 24 * 60 * 60 # Due in 2 days
child1$amount_due <- 50
child1$due_date <- Sys.time() + 5 * 24 * 60 * 60 # Due in 5 days
child2$amount_due <- 70
child2$due_date <- Sys.time() + 10 * 24 * 60 * 60 # Due in 10 days
# Compute total dues within next 7 days
total_due_7_days <- main_acc$compute_total_due_within_n_days(7)
print(total_due_7_days)
# Should return 100 + 50 = 150
} # }
## ------------------------------------------------
## Method `MainAccount$spending`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.5)
child2 <- ChildAccount$new("Child2", allocation = 0.5)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
# Simulate some deposits and withdrawals
main_acc$deposit(500, "T1", By = "User", channel = "Cash")
main_acc$withdraw(200, By = "User", channel = "Spending",
date = Sys.time() - 10)
child1$deposit(300, "T2", By = "User", channel = "Mobile")
child1$withdraw(100, By = "User", channel = "Shopping",
date = Sys.time() - 5)
# Get total user spending in last 30 days
main_acc$spending(c(Sys.Date() - 30, Sys.Date()))
# Should return 200 + 100 = 300
} # }
## ------------------------------------------------
## Method `MainAccount$total_income`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.5)
child2 <- ChildAccount$new("Child2", allocation = 0.5)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
# Simulate some deposits
main_acc$deposit(500, "TX01", By = "User", channel = "Cash",
date = Sys.time() - 7)
child1$deposit(300, "TX02", By = "User", channel = "Mobile",
date = Sys.time() - 3)
# Get total income in last 10 days
main_acc$total_income(c(Sys.Date() - 10, Sys.Date()))
# Should return 500 + 300 = 800
} # }
## ------------------------------------------------
## Method `MainAccount$allocated_amount`
## ------------------------------------------------
if (FALSE) { # \dontrun{
main_acc <- MainAccount$new("Main")
child1 <- ChildAccount$new("Child1", allocation = 0.5)
child2 <- ChildAccount$new("Child2", allocation = 0.5)
main_acc$add_child_account(child1)
main_acc$add_child_account(child2)
main_acc$deposit(1000, "TX001", By = "System", channel = "Bank",
date = Sys.time() - 5)
child1$deposit(300, "TX002", By = "User", channel = "Mobile",
date = Sys.time() - 3)
child2$deposit(200, "TX003", By = "User", channel = "Cash",
date = Sys.time() - 2)
# Get total allocated amount within last 7 days
main_acc$allocated_amount(c(Sys.Date() - 7, Sys.Date()))
# Expected output: 1000 (System) + 300 + 200 = 1500
} # }
## ------------------------------------------------
## Method `MainAccount$income_utilization`
## ------------------------------------------------
if (FALSE) { # \dontrun{
account <- MainAccount$new("Parent")
account$deposit(1000, "TX001", By = "System", channel = "Bank")
account$withdraw(200, By = "User", channel = "Mobile")
account$income_utilization()
# Expected output: 200 / 1000 = 0.2
} # }
## ------------------------------------------------
## Method `MainAccount$walking_amount`
## ------------------------------------------------
if (FALSE) { # \dontrun{
account$walking_amount("amount_due", c(Sys.Date() - 30,
Sys.Date()))
account$walking_amount("Balance", c(Sys.Date() - 7, Sys.Date()))
} # }