Permalink
Browse files

Minor update to increase Envelope compatibility with Mongo

  • Loading branch information...
1 parent a238a60 commit 81ce1eafedf629264e8a1cae5555727f14c7cd61 @dontangg committed Mar 26, 2012
Showing with 142 additions and 84 deletions.
  1. +87 −43 app/models/envelope.rb
  2. +6 −0 test/factories/envelopes.rb
  3. +49 −41 test/unit/envelope_test.rb
View
130 app/models/envelope.rb
@@ -14,22 +14,100 @@ class Envelope
scope :unassigned, where(unassigned: true)
scope :generic, where(income: false, unassigned: false)
- ##belongs_to :user
- ##belongs_to :parent_envelope, class_name: 'Envelope', foreign_key: 'parent_envelope_id'
- ##has_many :child_envelopes, class_name: 'Envelope', foreign_key: 'parent_envelope_id'
##has_many :transactions
##after_create :move_parents_transactions
##before_destroy :check_for_transactions
- ##serialize :expense, Expense
-
class << self
#def income
# self.first(conditions: {income: true}) #where(income: true)
#end
end
+ # This overrides the default to_param method that just returns id
+ def to_param
+ name.parameterize if id # I think that this needs to return nil if this envelope hasn't been saved
+ end
+
+ def parent_envelope_id=(new_id)
+ super
+ @parent_envelope = nil
+ end
+
+ def parent_envelope
+ if self.parent_envelope_id
+ @parent_envelope ||= self.user.envelopes.select { |envelope| envelope.id == self.parent_envelope_id }.first
+ else
+ nil
+ end
+ end
+
+ def parent_envelope=(new_parent_envelope)
+ @parent_envelope = nil
+ self.parent_envelope_id = new_parent_envelope.id
+ end
+
+ def child_envelopes
+ @child_envelopes ||= self.user.envelopes.select { |envelope| self.id == envelope.parent_envelope_id }
+ end
+
+ def self_and_child_envelope_ids
+ child_ids = [self.id]
+
+ child_envelopes.each do |child|
+ child_ids.concat child.self_and_child_envelope_ids
+ end
+
+ child_ids
+ end
+
+ def transactions(start_date, end_date = Date.today)
+ start_year_month = start_date.strftime("%Y-%m")
+ end_year_month = end_date.strftime("%Y-%m")
+ groups = TransactionGroup.where(:year_month.gte => start_year_month)
+ .and(:year_month.lte => end_year_month)
+ .and(:envelope_id.in => self_and_child_envelope_ids)
+ .desc(:year_month)
+ transactions = []
+ groups.each do |group|
+ group.transactions.each do |txn|
+ transactions << txn if txn.posted_at >= start_date && txn.posted_at <= end_date
+ end
+ end
+
+ # Sort by posted_at, then payee, then unique_count
+ transactions.sort! do |a, b|
+ result = b.posted_at <=> a.posted_at
+ if result == 0
+ result = a.payee <=> b.payee
+ if result == 0
+ result = a.unique_count <=> b.unique_count
+ end
+ end
+
+ result
+ end
+
+ transactions
+ end
+
+ def total_amount
+ unless @total_amount
+ # Add up all child envelopes transactions
+ @total_amount = child_envelopes.inject(0) { |running_total, child_envelope| running_total + (child_envelope.total_amount || 0) }
+
+ # Add up all my transactions
+ groups = TransactionGroup.where(envelope_id: self.id).only(:total_amount)
+ @total_amount = groups.inject(@total_amount) { |running_total, group| running_total + (group.total_amount || 0) }
+ end
+ @total_amount
+ end
+
+
+ ###############
+
+
attr_accessor :suggested_amount
def move_parents_transactions
@@ -58,19 +136,9 @@ def expense=(new_expense)
end
end
- # This overrides the default to_param method that just returns id
- # This causes our find method to still work because find calls to_i() on it which will just return the id
- def to_param
- "#{id}-#{name.parameterize}" if id
- end
-
- def total_amount
- @total_amount ||= read_attribute(:total_amount) || transactions.sum(:amount)
- end
-
- def total_amount=(new_amount)
- @total_amount = new_amount
- end
+ #def total_amount=(new_amount)
+ # @total_amount = new_amount
+ #end
def inclusive_total_amount(organized_envelopes = nil)
children = organized_envelopes.nil? ? self.child_envelopes : organized_envelopes[id]
@@ -83,9 +151,7 @@ def full_name(all_envelopes = nil)
name = if parent_envelope_id.nil?
self.name
else
- parent_envelope = all_envelopes ? all_envelopes.select {|envelope| envelope.id == self.parent_envelope_id}.first : Envelope.find(self.parent_envelope_id)
-
- parent_full_name = parent_envelope.full_name(all_envelopes)
+ parent_full_name = self.parent_envelope.full_name(all_envelopes)
"#{parent_full_name}: #{self.name}"
end
@@ -168,28 +234,6 @@ def self.add_funded_this_month(envelopes, user_id)
end
end
- def all_transactions(organized_envelopes = nil)
- if self.id == 0 && organized_envelopes.present? # All Transactions envelope
- all_child_envelope_ids = []
- organized_envelopes[nil].each do |envelope|
- all_child_envelope_ids.concat Envelope.all_child_envelope_ids(envelope.id, organized_envelopes)
- end
- all_child_envelope_ids.concat organized_envelopes['sys']
- else
- all_child_envelope_ids = Envelope.all_child_envelope_ids(self.id, organized_envelopes) << self.id
- end
- Transaction.where(envelope_id: all_child_envelope_ids)
- end
-
- def self.all_child_envelope_ids(envelope_id, organized_envelopes = nil)
- children = organized_envelopes ? organized_envelopes[envelope_id] : Envelope.where(parent_envelope_id: envelope_id)
- all_child_ids = children.map(&:id)
- children.each do |child|
- all_child_ids << all_child_envelope_ids(child.id, organized_envelopes)
- end
- all_child_ids.flatten
- end
-
def self.all_envelope(total_amount = nil)
env = Envelope.new(name: 'All Transactions')
env.total_amount = total_amount if total_amount
View
6 test/factories/envelopes.rb
@@ -2,6 +2,8 @@
FactoryGirl.define do
factory :envelope do
user { FactoryGirl.build(:user) }
+ income false
+ unassigned false
factory :income_envelope do
name 'Available Cash'
@@ -12,6 +14,10 @@
name 'Unassigned'
unassigned true
end
+
+ factory :auto_envelope do
+ name 'Auto'
+ end
end
end
View
90 test/unit/envelope_test.rb
@@ -1,9 +1,17 @@
require 'test_helper'
class EnvelopeTest < ActiveSupport::TestCase
+ def setup_envelopes
+ income_envelope = FactoryGirl.create(:income_envelope)
+ user = income_envelope.user
+ @user_id = user.id
+ FactoryGirl.create(:unassigned_envelope, user: user)
+ FactoryGirl.create(:auto_envelope, user: user)
+ end
+
test "income scope should return income envelopes" do
- user_id = FactoryGirl.create(:income_envelope).user.id
- envelope = User.find(user_id).envelopes.income.first
+ setup_envelopes
+ envelope = User.find(@user_id).envelopes.income.first
assert_equal "Available Cash", envelope.name
assert envelope.parent_envelope_id.nil?, "The income envelope should not have a parent envelope"
@@ -12,8 +20,8 @@ class EnvelopeTest < ActiveSupport::TestCase
end
test "unassigned scope should return unassigned envelopes" do
- user_id = FactoryGirl.create(:unassigned_envelope).user.id
- envelope = User.find(user_id).envelopes.unassigned.first
+ setup_envelopes
+ envelope = User.find(@user_id).envelopes.unassigned.first
assert "Unassigned", envelope.name
assert envelope.parent_envelope_id.nil?, "The unassigned envelope should not have a parent envelope"
@@ -22,27 +30,27 @@ class EnvelopeTest < ActiveSupport::TestCase
end
test "generic scope should return generic envelopes" do
- #user_id = FactoryGirl.create(:unassigned_envelope).user.id
- #envelope = User.find(user_id).envelopes.unassigned.first
+ setup_envelopes
+ envelopes = User.find(@user_id).envelopes.generic
- envelopes = Envelope.generic
+ assert !envelopes.empty?, "Can't do a proper test without any generic envelopes"
envelopes.each do |envelope|
- assert !envelope.income?
- assert !envelope.unassigned?
+ assert !envelope.income?, "Generic envelopes are not income envelopes"
+ assert !envelope.unassigned?, "Generic envelopes are not unassigned envelopes"
end
end
test "parent_envelope returns the parent envelope" do
- fuel_envelope = envelopes(:fuel)
- auto_envelope = envelopes(:auto)
+ auto_envelope = FactoryGirl.create(:envelope, name: 'Auto')
+ fuel_envelope = FactoryGirl.create(:envelope, name: 'Fuel', user: auto_envelope.user, parent_envelope: auto_envelope)
assert_equal auto_envelope, fuel_envelope.parent_envelope
end
test "child_envelopes returns the child envelopes" do
- fuel_envelope = envelopes(:fuel)
- auto_envelope = envelopes(:auto)
+ auto_envelope = FactoryGirl.create(:envelope, name: 'Auto')
+ fuel_envelope = FactoryGirl.create(:envelope, name: 'Fuel', user: auto_envelope.user, parent_envelope: auto_envelope)
assert auto_envelope.child_envelopes.include?(fuel_envelope)
end
@@ -65,21 +73,24 @@ class EnvelopeTest < ActiveSupport::TestCase
assert_equal :yearly, new_envelope.expense.frequency
end
- test "to_param returns id-name.parameterize" do
- envelope = envelopes(:available_cash)
+ test "to_param returns name.parameterize" do
+ auto_envelope = FactoryGirl.create(:envelope, name: 'Available Cash')
- assert_equal "#{envelope.id}-available-cash", envelope.to_param
+ assert_equal "available-cash", auto_envelope.to_param
end
- test "transactions scope returns all transactions for this envelope" do
- food_envelope = envelopes(:food)
- assert_equal 2, food_envelope.transactions.size
-
- auto_envelope = envelopes(:auto)
- assert_equal 0, auto_envelope.transactions.size
-
- cash_envelope = envelopes(:available_cash)
- assert_equal 1, cash_envelope.transactions.size
+ test "transactions scope returns all transactions and child transactions for this envelope" do
+ # Create envelopes
+ gifts_envelope = FactoryGirl.create(:envelope, name: 'Gifts')
+ holidays_envelope = FactoryGirl.create(:envelope, name: 'Holidays', user: gifts_envelope.user, parent_envelope: gifts_envelope)
+ christmas_envelope = FactoryGirl.create(:envelope, name: 'Christmas', user: gifts_envelope.user, parent_envelope: holidays_envelope)
+
+ # Create transactions
+ FactoryGirl.create(:transaction)
+
+ transactions = gifts_envelope.all_transactions(Date.today - 1.month)
+
+ assert_equal 3, transactions.size
end
test "total_amount returns sum of all transactions" do
@@ -93,26 +104,23 @@ class EnvelopeTest < ActiveSupport::TestCase
end
test "full_name returns this and parent envelope names separated by colons" do
- food_envelope = envelopes(:food)
- assert_equal "Food", food_envelope.full_name
-
- groceries_envelope = envelopes(:groceries)
- assert_equal "Food: Groceries", groceries_envelope.full_name
+ gifts_envelope = FactoryGirl.create(:envelope, name: 'Gifts')
+ holidays_envelope = FactoryGirl.create(:envelope, name: 'Holidays', user: gifts_envelope.user, parent_envelope: gifts_envelope)
+ christmas_envelope = FactoryGirl.create(:envelope, name: 'Christmas', user: gifts_envelope.user, parent_envelope: holidays_envelope)
+
+ assert_equal "Gifts", gifts_envelope.full_name
+ assert_equal "Gifts: Holidays", holidays_envelope.full_name
+ assert_equal "Gifts: Holidays: Christmas", christmas_envelope.full_name
end
- test "all_child_envelope_ids returns an array of all child envelope ids" do
- child_envelope_ids = Envelope.all_child_envelope_ids(envelopes(:gifts).id)
- assert_equal [envelopes(:holidays).id, envelopes(:christmas).id, envelopes(:valentines).id], child_envelope_ids
+ test "self_and_child_envelope_ids returns an array of all child envelope ids" do
+ auto_envelope = FactoryGirl.create(:envelope, name: 'Auto')
+ fuel_envelope = FactoryGirl.create(:envelope, name: 'Fuel', user: auto_envelope.user, parent_envelope: auto_envelope)
+
+ child_envelope_ids = auto_envelope.self_and_child_envelope_ids
+ assert_equal [auto_envelope.id, fuel_envelope.id], child_envelope_ids
end
- test "all_transactions returns all transactions for that envelope and all children" do
- sql = envelopes(:gifts).all_transactions(nil).to_sql
- assert sql.include?(envelopes(:gifts).id.to_s)
- assert sql.include?(envelopes(:holidays).id.to_s)
- assert sql.include?(envelopes(:christmas).id.to_s)
- assert sql.include?(envelopes(:valentines).id.to_s)
- end
-
test "amount_funded_this_month returns a sum of the positive transaction amounts" do
amount = envelopes(:groceries).amount_funded_this_month.to_f

0 comments on commit 81ce1ea

Please sign in to comment.