REFACTOR Migrates to single 'amount' field for transactions
Refactors the data model to use a single 'amount' field for journal entry lines, aligning with the Beancount approach. This simplifies the model, enhances compatibility, and eliminates invalid states. Includes a database migration to convert existing debit/credit columns to the new 'amount' field. Updates balance calculation logic to utilize the new amount field for improved accuracy and efficiency.
This commit is contained in:
parent
0b50ba0f82
commit
5cc2630777
7 changed files with 196 additions and 144 deletions
|
|
@ -23,13 +23,13 @@ def validate_journal_entry(
|
|||
entry_lines: List[Dict[str, Any]]
|
||||
) -> None:
|
||||
"""
|
||||
Validate a journal entry and its lines.
|
||||
Validate a journal entry and its lines (Beancount-style with single amount field).
|
||||
|
||||
Checks:
|
||||
1. Entry must have at least 2 lines (double-entry requirement)
|
||||
2. Entry must be balanced (sum of debits = sum of credits)
|
||||
3. All lines must have valid amounts (non-negative)
|
||||
4. All lines must have account_id
|
||||
2. Entry must be balanced (sum of amounts = 0)
|
||||
3. All lines must have account_id
|
||||
4. No line should have amount = 0 (would serve no purpose)
|
||||
|
||||
Args:
|
||||
entry: Journal entry dict with keys:
|
||||
|
|
@ -38,8 +38,7 @@ def validate_journal_entry(
|
|||
- entry_date: datetime
|
||||
entry_lines: List of entry line dicts with keys:
|
||||
- account_id: str
|
||||
- debit: int
|
||||
- credit: int
|
||||
- amount: int (positive = debit, negative = credit)
|
||||
|
||||
Raises:
|
||||
ValidationError: If validation fails
|
||||
|
|
@ -66,64 +65,30 @@ def validate_journal_entry(
|
|||
}
|
||||
)
|
||||
|
||||
# Check amounts are non-negative
|
||||
debit = line.get("debit", 0)
|
||||
credit = line.get("credit", 0)
|
||||
# Get amount (Beancount-style: positive = debit, negative = credit)
|
||||
amount = line.get("amount", 0)
|
||||
|
||||
if debit < 0:
|
||||
# Check that amount is non-zero (zero amounts serve no purpose)
|
||||
if amount == 0:
|
||||
raise ValidationError(
|
||||
f"Entry line {i + 1} has negative debit: {debit}",
|
||||
{
|
||||
"entry_id": entry.get("id"),
|
||||
"line_index": i,
|
||||
"debit": debit,
|
||||
}
|
||||
)
|
||||
|
||||
if credit < 0:
|
||||
raise ValidationError(
|
||||
f"Entry line {i + 1} has negative credit: {credit}",
|
||||
{
|
||||
"entry_id": entry.get("id"),
|
||||
"line_index": i,
|
||||
"credit": credit,
|
||||
}
|
||||
)
|
||||
|
||||
# Check that a line doesn't have both debit and credit
|
||||
if debit > 0 and credit > 0:
|
||||
raise ValidationError(
|
||||
f"Entry line {i + 1} has both debit and credit",
|
||||
{
|
||||
"entry_id": entry.get("id"),
|
||||
"line_index": i,
|
||||
"debit": debit,
|
||||
"credit": credit,
|
||||
}
|
||||
)
|
||||
|
||||
# Check that a line has at least one non-zero amount
|
||||
if debit == 0 and credit == 0:
|
||||
raise ValidationError(
|
||||
f"Entry line {i + 1} has both debit and credit as zero",
|
||||
f"Entry line {i + 1} has amount = 0 (serves no purpose)",
|
||||
{
|
||||
"entry_id": entry.get("id"),
|
||||
"line_index": i,
|
||||
}
|
||||
)
|
||||
|
||||
# Check entry is balanced
|
||||
total_debits = sum(line.get("debit", 0) for line in entry_lines)
|
||||
total_credits = sum(line.get("credit", 0) for line in entry_lines)
|
||||
# Check entry is balanced (sum of amounts must equal 0)
|
||||
# Beancount-style: positive amounts cancel out negative amounts
|
||||
total_amount = sum(line.get("amount", 0) for line in entry_lines)
|
||||
|
||||
if total_debits != total_credits:
|
||||
if total_amount != 0:
|
||||
raise ValidationError(
|
||||
"Journal entry is not balanced",
|
||||
"Journal entry is not balanced (sum of amounts must equal 0)",
|
||||
{
|
||||
"entry_id": entry.get("id"),
|
||||
"total_debits": total_debits,
|
||||
"total_credits": total_credits,
|
||||
"difference": total_debits - total_credits,
|
||||
"total_amount": total_amount,
|
||||
"line_count": len(entry_lines),
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue