forked from jamis/bucketwise
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
26 changed files
with
858 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module CategorizedItems | ||
def deposits | ||
@deposits ||= to_a.select { |item| item.amount > 0 } | ||
end | ||
|
||
def checks | ||
@checks ||= to_a.select { |item| item.amount < 0 && item.event.check_number.present? } | ||
end | ||
|
||
def expenses | ||
@expenses ||= to_a.select { |item| item.amount < 0 && item.event.check_number.blank? } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
class StatementsController < ApplicationController | ||
before_filter :find_account, :only => %w(index new create) | ||
before_filter :find_statement, :only => %w(show edit update destroy) | ||
|
||
def index | ||
@statements = account.statements.balanced | ||
end | ||
|
||
def new | ||
@statement = account.statements.build(:ending_balance => account.balance, | ||
:occurred_on => Date.today) | ||
end | ||
|
||
def create | ||
@statement = account.statements.create(params[:statement]) | ||
redirect_to(edit_statement_url(@statement)) | ||
end | ||
|
||
def show | ||
end | ||
|
||
def edit | ||
@uncleared = account.account_items.uncleared(:with => statement, :include => :event) | ||
end | ||
|
||
def update | ||
statement.update_attributes(params[:statement]) | ||
redirect_to(account) | ||
end | ||
|
||
def destroy | ||
statement.destroy | ||
redirect_to(account) | ||
end | ||
|
||
protected | ||
|
||
attr_reader :uncleared, :statements | ||
helper_method :uncleared, :statements | ||
|
||
attr_reader :account, :statement | ||
helper_method :account, :statement | ||
|
||
def find_account | ||
@account = Account.find(params[:account_id]) | ||
@subscription = user.subscriptions.find(@account.subscription_id) | ||
end | ||
|
||
def find_statement | ||
@statement = Statement.find(params[:id]) | ||
@account = @statement.account | ||
@subscription = user.subscriptions.find(@account.subscription_id) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
module StatementsHelper | ||
def uncleared_row_class(item) | ||
classes = [cycle('odd', 'even')] | ||
classes << "cleared" if item.statement_id | ||
classes.join(" ") | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
class Statement < ActiveRecord::Base | ||
belongs_to :account | ||
has_many :account_items, :extend => CategorizedItems, :dependent => :nullify | ||
|
||
before_create :initialize_starting_balance | ||
after_save :associate_account_items_with_self | ||
|
||
named_scope :pending, :conditions => { :balanced_at => nil } | ||
named_scope :balanced, :conditions => "balanced_at IS NOT NULL" | ||
|
||
attr_accessible :occurred_on, :ending_balance, :cleared | ||
|
||
validates_presence_of :occurred_on, :ending_balance | ||
|
||
def ending_balance=(amount) | ||
if amount.is_a?(Float) || amount =~ /[.,]/ | ||
amount = (amount.to_s.tr(",", "").to_f * 100).to_i | ||
end | ||
|
||
super(amount) | ||
end | ||
|
||
def balance | ||
ending_balance | ||
end | ||
|
||
def balanced?(reload=false) | ||
unsettled_balance(reload).zero? | ||
end | ||
|
||
def settled_balance(reload=false) | ||
@settled_balance = nil if reload | ||
@settled_balance ||= account_items.to_a.sum(&:amount) | ||
end | ||
|
||
def unsettled_balance(reload=false) | ||
@unsettled_balance = nil if reload | ||
@unsettled_balance ||= starting_balance + settled_balance(reload) - ending_balance | ||
end | ||
|
||
def cleared=(ids) | ||
@ids_to_clear = ids | ||
@already_updated = false | ||
end | ||
|
||
protected | ||
|
||
def initialize_starting_balance | ||
self.starting_balance ||= account.statements.balanced.last.try(:ending_balance) || 0 | ||
end | ||
|
||
def associate_account_items_with_self | ||
return if @already_updated | ||
@already_updated = true | ||
|
||
account_items.clear | ||
|
||
ids = connection.select_values(sanitize_sql([<<-SQL.squish, account_id, ids_to_clear])) | ||
SELECT ai.id | ||
FROM account_items ai | ||
WHERE ai.account_id = ? | ||
AND ai.id IN (?) | ||
SQL | ||
|
||
connection.update(sanitize_sql([<<-SQL.squish, id, ids])) | ||
UPDATE account_items | ||
SET statement_id = ? | ||
WHERE id IN (?) | ||
SQL | ||
|
||
account_items.reset | ||
|
||
if @ids_to_clear | ||
if balanced?(true) && !balanced_at | ||
update_attribute :balanced_at, Time.now.utc | ||
elsif !balanced? && balanced_at | ||
update_attribute :balanced_at, nil | ||
end | ||
end | ||
end | ||
|
||
private | ||
|
||
def sanitize_sql(sql) | ||
self.class.send(:sanitize_sql, sql) | ||
end | ||
|
||
def ids_to_clear | ||
@ids_to_clear || [] | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,13 @@ | ||
%span.actions== #{link_to_function("Rename", "Accounts.rename(#{account_path(account).to_json}, #{account.name.to_json}, #{form_authenticity_token.to_json})")} | #{link_to("Delete", account_path(account), :method => :delete, :confirm => "Are you sure you want to delete this account?")} | ||
%span.actions | ||
- if account.statements.pending.any? | ||
= link_to("Resume reconciling", edit_statement_path(account.statements.pending.first)) | ||
- else | ||
= link_to("Reconcile", new_account_statement_path(account)) | ||
| | ||
- if account.statements.balanced.any? | ||
= link_to("Prior statements", account_statements_path(account)) | ||
| | ||
= link_to_function("Rename", "Accounts.rename(#{account_path(account).to_json}, #{account.name.to_json}, #{form_authenticity_token.to_json})") | ||
| | ||
= link_to("Delete", account_path(account), :method => :delete, :confirm => "Are you sure you want to delete this account?") | ||
&= account.name |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,10 @@ | ||
%tr.current_balance | ||
%th.date= Date.today.strftime("%Y-%m-%d") | ||
%th Current balance | ||
- if container.is_a?(Statement) | ||
%th.date= statement.occurred_on.strftime("%Y-%m-%d") | ||
%th Ending balance | ||
- else | ||
%th.date= Date.today.strftime("%Y-%m-%d") | ||
%th Current balance | ||
%th.number.total.balance{:colspan => 2}= balance_cell(container, :tag => "span", :id => "balance") | ||
%tr.spacer | ||
%td{:colspan => 4} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.subtotal | ||
.settled | ||
Subtotal: | ||
%span.subtotal_dollars= format_cents(subtotal) | ||
.remaining | ||
Remaining: | ||
%span.remaining_dollars{:class => statement.unsettled_balance.zero? ? "balanced" : nil} | ||
= format_cents(statement.unsettled_balance) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
%tr{:id => dom_id(uncleared), :class => uncleared_row_class(uncleared)} | ||
%td.checkbox= check_box_tag "statement[cleared][]", uncleared.id, uncleared.statement_id, :id => dom_id(uncleared, :check), :onclick => "Statements.toggleCleared(#{uncleared.id})" | ||
%td.date{:onclick => "Statements.clickItem(#{uncleared.id})"}= uncleared.occurred_on.strftime("%Y-%m-%d") | ||
- if uncleared.event.check_number | ||
%td.check{:onclick => "Statements.clickItem(#{uncleared.id})"}= "#" + uncleared.event.check_number.to_s | ||
%td.actor{:onclick => "Statements.clickItem(#{uncleared.id})"}&= uncleared.event.actor | ||
%td.number{:onclick => "Statements.clickItem(#{uncleared.id})"} | ||
%span{:style => "display: none;", :id => dom_id(uncleared, :amount)}= uncleared.amount | ||
= format_cents(uncleared.amount.abs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#data.content | ||
%h2== Balance your statement | ||
|
||
.statement.edit.form | ||
|
||
- form_for(statement) do |form| | ||
|
||
%table.general | ||
%tr | ||
%th.occurred_on Statement date | ||
%th.starting_balance Starting balance | ||
%th.ending_balance Ending balance | ||
%tr | ||
%td.occurred_on= form.calendar_date_select :occurred_on, :size => 10 | ||
%td#starting_balance.starting_balance.number= format_cents(statement.starting_balance) | ||
%td.ending_balance= "$" + form.text_field(:ending_balance, :size => 8, :class => "number", :value => format_cents(statement.ending_balance, :unit => ""), :onchange => "Statements.updateBalances()") | ||
|
||
- if uncleared.deposits.any? | ||
%fieldset#deposits | ||
%legend Deposits | ||
|
||
.uncleared.deposits | ||
%table= render :partial => "statements/uncleared", :collection => uncleared.deposits | ||
|
||
= render :partial => "statements/subtotal", :object => statement.account_items.deposits.sum(&:amount) | ||
|
||
- if uncleared.checks.any? | ||
%fieldset#checks | ||
%legend Checks | ||
|
||
.uncleared.checks | ||
%table= render :partial => "statements/uncleared", :collection => uncleared.checks | ||
|
||
= render :partial => "statements/subtotal", :object => statement.account_items.checks.sum(&:amount) | ||
|
||
- if uncleared.expenses.any? | ||
%fieldset#expenses | ||
%legend Other expenses | ||
|
||
.uncleared.expenses | ||
%table= render :partial => "statements/uncleared", :collection => uncleared.expenses | ||
|
||
= render :partial => "statements/subtotal", :object => statement.account_items.expenses.sum(&:amount) | ||
|
||
#balanced{:style => visible?(statement.balanced?)} | ||
%h3 Congratulations! | ||
|
||
%p Your records exactly match your account statement, and everything balances. | ||
|
||
%p= form.submit "Close out this statement" | ||
|
||
%p#actions{:style => visible?(!statement.balanced?)} | ||
= form.submit "Save for later" | ||
or | ||
= link_to("abort this reconciliation", statement_path(statement), :method => :delete, :confirm => "Are you sure you want to discard this reconciliation?") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#data.content | ||
.navigation | ||
= link_to "Dashboard", subscription_path(subscription) | ||
= link_to h(account.name), account_path(account) | ||
|
||
%h2 Previous Statements | ||
|
||
- if statements.empty? | ||
%p== You have not yet balanced this account against any statements from your financial institution. You may start by clicking #{link_to("here", new_account_statement_path(account))}, to begin balancing this account. | ||
|
||
- else | ||
%ul | ||
- statements.each do |statement| | ||
%li | ||
= link_to(statement.occurred_on.strftime("%Y-%m-%d"), statement_path(statement)) | ||
= ":" | ||
= format_cents(statement.ending_balance) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#data.content | ||
%h2== Let's reconcile your #{h(account.name)} account | ||
|
||
.form | ||
|
||
- form_for([account, statement]) do |form| | ||
|
||
%fieldset | ||
|
||
%p First, take a look at the account statement from your bank or other financial institution. | ||
|
||
%p If you haven't reconciled in a while, make sure you start with the <em>oldest</em> statement and work forward. | ||
|
||
%p | ||
<strong>When</strong> was the statement printed? | ||
= form.calendar_date_select :occurred_on, :size => 10 | ||
|
||
%p | ||
<strong>What</strong> is the ending balance? | ||
= "$" + form.text_field(:ending_balance, :size => 8, :class => "number", :value => format_cents(statement.ending_balance, :unit => ""), :onchange => "this.value = Money.format(this)") | ||
|
||
%p | ||
= form.submit "Go to step #2" | ||
or | ||
= link_to("cancel", account_path(account)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#data.content | ||
.navigation | ||
= link_to "Dashboard", subscription_path(subscription) | ||
= link_to h(account.name), account_path(account) | ||
= link_to "Prior statements", account_statements_path(account) | ||
|
||
%h2 | ||
%span.actions | ||
= link_to("Delete", statement_path(statement), :confirm => "Are you sure you want to delete this statement?", :method => :delete) | ||
Statement for period ending | ||
= statement.occurred_on.strftime("%Y-%m-%d") | ||
|
||
%table.entries | ||
= render :partial => "events/balance", :locals => { :container => statement } | ||
= render(statement.account_items) |
Oops, something went wrong.