Class: Admin::PaymentsController

Inherits:
ApplicationController
  • Object
show all
Includes:
AdminLayoutHelper, ApplicationHelper, ExtensibleObjectHelper
Defined in:
app/controllers/admin/payments_controller.rb

Defined Under Namespace

Classes: ObservedInvalidAmount

Constant Summary collapse

VALID_INVOICE_ASSIGNMENT_INPUT =
/^invoice_assignments_([\d]+)_amount$/
VALID_MONEY_INPUT =
/^(?:[ ]*([\d]+\.[\d]{0,2}|[\d]+)[ ]*|)$/

Instance Method Summary collapse

Methods included from ApplicationHelper

#controller_id, #define_application_layout_variables, #h_money, #money_for_input

Methods included from ExtensibleObjectHelper

append_features

Methods included from AdminLayoutHelper

append_features, #controller_url, #define_layout_variables

Instance Method Details

#before_update_save(payment) ⇒ Object Also known as: before_create_save

In here we update all the invoice assignments



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'app/controllers/admin/payments_controller.rb', line 80

def before_update_save(payment)
  # Let's create a lookup map from the input params to make this easier:
  input_assignments = {}
  params[:record][:invoice_assignments].try(:each_pair) do |inv_id, fields|
    input_assignments[inv_id.to_i] = Money.new(fields[:amount].tr('^\-0-9','').to_i)
  end

  assignment_deletes = []
  # First we iterate through the existing relationships:
  payment.invoice_assignments.each do |asgn|
    # Did the assignment get changed by the input? If so...
    if (
      input_assignments.has_key?(asgn.invoice_id) && 
      input_assignments[asgn.invoice_id] != asgn.amount
    )
      # They set this asignment to zero - which means we remove the assignment:
      if input_assignments[asgn.invoice_id] == Money.new(0)
        # Mark this assignment for deletion below
        assignment_deletes << asgn
      else # assign the new value:
        asgn.amount = input_assignments[asgn.invoice_id]
      end
    end
  end

  # THis is a little more efficient than deleting in the loop above. Also,
  # I think there's a bug whereby the iterator stops running as soon as you delete somethign in the 
  # assignment collection. This causes subsequent assignments not to run..
  payment.invoice_assignments.delete *assignment_deletes
  
  # And then we go through the open invoices to find if new assignments need to be created:
  payment.client.unpaid_invoices.each do |inv|
    # We need to add a new assignment if there's a non-zero value
    payment.invoice_assignments.build(
        :invoice_id => inv.id, 
        :amount => input_assignments[inv.id]
      ) if (
      # We want to make sure we're not creating an assignment that already exists
      !payment.invoice_assignments.any?{|asgn| asgn.invoice_id == inv.id} &&
      input_assignments.has_key?(inv.id) &&
      input_assignments[inv.id] != Money.new(0)
    )
  end
end

#on_assignment_observationObject



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'app/controllers/admin/payments_controller.rb', line 127

def on_assignment_observation
  @observed_column = params[:observed_column]

  # First let's load the record in question (or create one) ...
  @record = (/^[\d]+$/.match(params[:record_id])) ? 
    Payment.find(params[:record_id].to_i) : Payment.new

  # We'll need these later in the helper/rjs...
  params[:id] = params[:record_id] # This is a hack to make the options_for_column work as expected
  define_scaffold_observations

  # We don't have to raise on this one really. Its not consequential if this is screwy
  @record.client_id = params[:client].to_i if /^[\d]+$/.match params[:client]

  # Let's make sure all the amounts we've been given are acceptable:
  @invalid_amount_columns = params.to_enum(:each_pair).collect{|key,value| 
    key if (VALID_INVOICE_ASSIGNMENT_INPUT.match key or key == 'amount') and !VALID_MONEY_INPUT.match value
  }.compact

  if @invalid_amount_columns.length > 0
    # We'll end up needing this when we're clearing out amounts outstanding due to a mis-type
    @invoice_map = Invoice.find(
      :all,
      :conditions => ['id IN (?)', @invalid_amount_columns.collect{|colname| $1 if VALID_INVOICE_ASSIGNMENT_INPUT.match colname}]
    ).inject({}){|ret, inv| ret.merge({inv.id => inv})}
    
    raise ObservedInvalidAmount
  end

  # This is an important field to get right. Remember that we already validating this param above:
  @record.amount = Money.new(params[:amount].to_f*100) if params.has_key? :amount

  case @observed_column
    when /^(?:amount|client)$/
      # Let's try to guess the right assignments automatically:
      @record.invoice_assignments = @record.client.recommend_invoice_assignments_for(
        @record.amount
      ) if @record.client and @record.amount

    when VALID_INVOICE_ASSIGNMENT_INPUT
      @observed_invoice = Invoice.find $1.to_i

      update_assignments_from_params @record

      @observed_assignment = @record.invoice_assignments.to_a.find{|ia| ia.invoice_id == @observed_invoice.id}
  end

  rescue ObservedInvalidAmount
    render :action => :observation_error
end