1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-05 13:35:21 +02:00

Fix Account Holding validation and synchronization (#1818)

* Fix Account Holding validation and synchronization

Fixes #1781

- Add comprehensive validations for Account::Holding
- Implement validation to ensure amount matches qty * price
- Update Account::Syncer to include qty and price during synchronization
- Add database constraints for holding attributes and calculations

* Remove database check constraints for Account Holdings

Align with project convention of keeping complex validations in ActiveRecord
- Remove database-level check constraints for quantity, price, and amount
- Maintain database-level null and unique constraints
- Prepare for more flexible validation in the model layer
This commit is contained in:
Josh Pigford 2025-02-07 10:42:01 -06:00 committed by GitHub
parent 0dc25cda22
commit cf23673003
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 67 additions and 9 deletions

View file

@ -6,7 +6,9 @@ class Account::Holding < ApplicationRecord
belongs_to :account
belongs_to :security
validates :qty, :currency, presence: true
validates :qty, :currency, :date, :price, :amount, presence: true
validates :qty, :price, :amount, numericality: { greater_than_or_equal_to: 0 }
validate :amount_matches_qty_and_price
scope :chronological, -> { order(:date) }
scope :for, ->(security) { where(security_id: security).order(:date) }
@ -62,4 +64,13 @@ class Account::Holding < ApplicationRecord
current: amount_money,
previous: start_amount
end
def amount_matches_qty_and_price
return if qty.blank? || price.blank? || amount.blank?
expected_amount = qty * price
return if amount == expected_amount
errors.add(:amount, "must equal qty * price (expected: #{expected_amount})")
end
end

View file

@ -99,6 +99,8 @@ class Account::Syncer
account.holdings.build(
security: holding.security,
date: holding.date,
qty: holding.qty,
price: exchange_rate.rate * holding.price,
amount: exchange_rate.rate * holding.amount,
currency: to_currency
)