132 lines
3.8 KiB
GDScript
132 lines
3.8 KiB
GDScript
class_name LedgerEntry
|
|
extends RefCounted
|
|
|
|
## One immutable-in-practice double-entry ledger line.
|
|
##
|
|
## A debit increases the signed balance of debit_account and a credit decreases
|
|
## the signed balance of credit_account. EconomyService is the only component
|
|
## which may append entries or update its derived balance cache.
|
|
|
|
var transaction_id: StringName = &""
|
|
var absolute_minute := 0
|
|
var debit_account: StringName = &""
|
|
var credit_account: StringName = &""
|
|
var amount := 0
|
|
var category: StringName = &""
|
|
var source_entity_id: StringName = &""
|
|
var related_transaction_id: StringName = &""
|
|
var memo_key: StringName = &""
|
|
|
|
|
|
func configure(
|
|
p_transaction_id: StringName,
|
|
p_absolute_minute: int,
|
|
p_debit_account: StringName,
|
|
p_credit_account: StringName,
|
|
p_amount: int,
|
|
p_category: StringName,
|
|
p_source_entity_id: StringName = &"",
|
|
p_related_transaction_id: StringName = &"",
|
|
p_memo_key: StringName = &""
|
|
) -> LedgerEntry:
|
|
transaction_id = p_transaction_id
|
|
absolute_minute = p_absolute_minute
|
|
debit_account = p_debit_account
|
|
credit_account = p_credit_account
|
|
amount = p_amount
|
|
category = p_category
|
|
source_entity_id = p_source_entity_id
|
|
related_transaction_id = p_related_transaction_id
|
|
memo_key = p_memo_key
|
|
return self
|
|
|
|
|
|
func validation_errors() -> Array[StringName]:
|
|
var errors: Array[StringName] = []
|
|
if transaction_id.is_empty():
|
|
errors.append(&"EMPTY_TRANSACTION_ID")
|
|
if absolute_minute < 0:
|
|
errors.append(&"INVALID_ABSOLUTE_MINUTE")
|
|
if debit_account.is_empty():
|
|
errors.append(&"EMPTY_DEBIT_ACCOUNT")
|
|
if credit_account.is_empty():
|
|
errors.append(&"EMPTY_CREDIT_ACCOUNT")
|
|
if not debit_account.is_empty() and debit_account == credit_account:
|
|
errors.append(&"IDENTICAL_ACCOUNTS")
|
|
if amount <= 0:
|
|
errors.append(&"INVALID_AMOUNT")
|
|
if category.is_empty():
|
|
errors.append(&"EMPTY_CATEGORY")
|
|
if not related_transaction_id.is_empty() and related_transaction_id == transaction_id:
|
|
errors.append(&"SELF_RELATED_TRANSACTION")
|
|
return errors
|
|
|
|
|
|
func is_valid() -> bool:
|
|
return validation_errors().is_empty()
|
|
|
|
|
|
func reversed(
|
|
p_transaction_id: StringName,
|
|
p_absolute_minute: int,
|
|
p_category: StringName = &"REVERSAL",
|
|
p_source_entity_id: StringName = &"",
|
|
p_memo_key: StringName = &""
|
|
) -> LedgerEntry:
|
|
return LedgerEntry.new().configure(
|
|
p_transaction_id,
|
|
p_absolute_minute,
|
|
credit_account,
|
|
debit_account,
|
|
amount,
|
|
p_category,
|
|
p_source_entity_id if not p_source_entity_id.is_empty() else source_entity_id,
|
|
transaction_id,
|
|
p_memo_key
|
|
)
|
|
|
|
|
|
func copy() -> LedgerEntry:
|
|
return LedgerEntry.new().configure(
|
|
transaction_id,
|
|
absolute_minute,
|
|
debit_account,
|
|
credit_account,
|
|
amount,
|
|
category,
|
|
source_entity_id,
|
|
related_transaction_id,
|
|
memo_key
|
|
)
|
|
|
|
|
|
func to_dictionary() -> Dictionary:
|
|
return {
|
|
&"transaction_id": String(transaction_id),
|
|
&"absolute_minute": absolute_minute,
|
|
&"debit_account": String(debit_account),
|
|
&"credit_account": String(credit_account),
|
|
&"amount": amount,
|
|
&"category": String(category),
|
|
&"source_entity_id": String(source_entity_id),
|
|
&"related_transaction_id": String(related_transaction_id),
|
|
&"memo_key": String(memo_key),
|
|
}
|
|
|
|
|
|
static func from_dictionary(data: Dictionary) -> LedgerEntry:
|
|
return LedgerEntry.new().configure(
|
|
StringName(data.get(&"transaction_id", data.get("transaction_id", ""))),
|
|
int(data.get(&"absolute_minute", data.get("absolute_minute", -1))),
|
|
StringName(data.get(&"debit_account", data.get("debit_account", ""))),
|
|
StringName(data.get(&"credit_account", data.get("credit_account", ""))),
|
|
int(data.get(&"amount", data.get("amount", 0))),
|
|
StringName(data.get(&"category", data.get("category", ""))),
|
|
StringName(data.get(&"source_entity_id", data.get("source_entity_id", ""))),
|
|
StringName(data.get(
|
|
&"related_transaction_id",
|
|
data.get("related_transaction_id", "")
|
|
)),
|
|
StringName(data.get(&"memo_key", data.get("memo_key", "")))
|
|
)
|