diff --git a/TODO.txt b/TODO.txt index 0a605eb..0673c26 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,16 +1,8 @@ - -Invoices: -* We should add an Draft Invoices controller and rename Invoices to 'All' Invoices... - * All we need to do now is the submit. make sure we dim the buttons and run the spinner while generating - * Why does the Create New not destroy the batch div? It should ... - -* BUG: Add Existing Client Reps is borked. We're only showing from the existing company - not all the available (see the LDI) - -* Assign version numbers to the invoice based on the number of times an invoice is published... - * I don't know if we should/need-to adjust the invoice pdfs out here just yet .... - activities_with_prices: * Move_to_invoice function should allow us to Move_to '(Unassigned)', and ideally that would be a radio group + * Get the move to nil unit test working + +TODO: I think the dates on the Batch create aren't getting created right... test to make sure they equal the input * We may want to go through the controllers and modify the searches a bit: config.columns[:clients].search_sql @@ -34,6 +26,9 @@ activities_with_prices: * Ideally we have that DraftInvoices/ "Batch Create" link to the left of Create.. +* Assign version numbers to the invoice based on the number of times an invoice is published... + * I don't know if we should/need-to adjust the invoice pdfs out here just yet .... + * Slimtimer-less time entry * http://dhtmlx.com/docs/products/dhtmlxScheduler/index.shtml diff --git a/app/controllers/admin/activities_with_prices_controller.rb b/app/controllers/admin/activities_with_prices_controller.rb index 1e6270b..6540f27 100644 --- a/app/controllers/admin/activities_with_prices_controller.rb +++ b/app/controllers/admin/activities_with_prices_controller.rb @@ -55,7 +55,10 @@ def move_to_invoice if params.has_key? :move_to_invoice_id begin - invoice_dest = Invoice.find(params[:move_to_invoice_id].to_i) + invoice_dest = (params[:move_to_invoice_id].empty?) ? + nil : + Invoice.find(params[:move_to_invoice_id].to_i) + activity.move_to_invoice invoice_dest do_list @@ -65,9 +68,9 @@ def move_to_invoice @errors_during_move << $! end - render :action => 'move_to_invoice.js.rjs' + render :action => 'move_to_invoice.js' else - render :action => 'move_to_invoice.html.erb', :layout => false + render :action => 'move_to_invoice.html', :layout => false end end diff --git a/app/controllers/admin/client_representatives_controller.rb b/app/controllers/admin/client_representatives_controller.rb index 8472092..784836b 100644 --- a/app/controllers/admin/client_representatives_controller.rb +++ b/app/controllers/admin/client_representatives_controller.rb @@ -48,7 +48,7 @@ def merge_conditions(*conditions) existing_association_ids = parent_record.send('%s_ids' % params[:parent_column].singularize) if parent_record - (existing_association_ids) ? + (existing_association_ids.try(:length) > 0) ? ['`client_representatives`.id NOT IN (?)', existing_association_ids] : nil else diff --git a/app/controllers/admin/draft_invoices_controller.rb b/app/controllers/admin/draft_invoices_controller.rb index b1efac5..74fbdf3 100644 --- a/app/controllers/admin/draft_invoices_controller.rb +++ b/app/controllers/admin/draft_invoices_controller.rb @@ -29,13 +29,8 @@ def self.active_scaffold_paths def batch_create_on_date_change # This is kind of an annoying way to make a date ... - @invoice_date_at = Time.utc( - params[:batch_invoice_date_at][:year].to_i, - params[:batch_invoice_date_at][:month].to_i, - params[:batch_invoice_date_at][:day].to_i, - params[:batch_invoice_date_at][:hour].to_i, - params[:batch_invoice_date_at][:minute].to_i, - params[:batch_invoice_date_at][:second].to_i + @invoice_date_at = utc_date_from_param( + params[:batch_invoice_date_at] ) if params[:batch_invoice_date_at] # I didn't really feel the need to create a partial just for this one line: @@ -44,13 +39,51 @@ def batch_create_on_date_change def batch_create if params.has_key? :batch_client - render(:update){|page| page << "alert('yoyoyoy');"} + invoiceable_client_ids = params[:batch_client].keys.collect(&:to_i) + + if invoiceable_client_ids.length > 0 + all_activity_types = ActivityType.find(:all) + + invoice_date = utc_date_from_param params[:batch_invoice_date_at] + + @new_invoices = Client.find( + :all, + :conditions => ['id IN (?)', invoiceable_client_ids] + ).each do |client| + Invoice.create!( + :client => client, + :activity_types => all_activity_types, + :activities => Invoice.recommended_activities_for( + client.id, + invoice_date, + all_activity_types + ) + ) + end + + do_list + end + + render :action => 'batch_create.js' else @invoice_date_at = Time.utc(*Time.now.to_a).prev_month.end_of_month - render :action => :batch_create, :layout => false + render :action => 'batch_create.html', :layout => false end end + private + + def utc_date_from_param(date_hash) + Time.utc( + date_hash[:year].to_i, + date_hash[:month].to_i, + date_hash[:day].to_i, + date_hash[:hour].to_i, + date_hash[:minute].to_i, + date_hash[:second].to_i + ) + end + handle_extensions invoices_scaffold_init diff --git a/app/models/activity.rb b/app/models/activity.rb index c5b981f..87569f4 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -95,11 +95,15 @@ def move_to_invoice(dest) dest_invoice = (dest.class == Integer) ? Invoice.find(dest) : dest raise StandardError, "Can't move an already-published activity." if is_published? - raise StandardError, "Can't move an activity to an already published invoice." if dest_invoice.is_published? + raise StandardError, "Can't move an activity to an already published invoice." if dest_invoice.try(:is_published?) - self.invoice_id = dest_invoice.id - self.client_id = dest_invoice.client_id - + self.invoice_id = (dest_invoice.nil?) ? 0 : dest_invoice.id + self.client_id = dest_invoice.client_id unless dest_invoice.nil? + +if self.invoice_id == 0 + puts "A:"+self.changed_attributes.inspect + puts "D:"+self.dirty?.inspect +end @dont_validate_type_associations = true save! diff --git a/app/views/admin/activities_with_prices/move_to_invoice.html.erb b/app/views/admin/activities_with_prices/move_to_invoice.html.erb index f2cccc8..82cc315 100644 --- a/app/views/admin/activities_with_prices/move_to_invoice.html.erb +++ b/app/views/admin/activities_with_prices/move_to_invoice.html.erb @@ -28,14 +28,14 @@ <%= select_tag( 'move_to_invoice_id', options_for_select( - @dest_invoices.collect{|inv| [inv.long_name, inv.id]}, + [['(None)', nil]]+@dest_invoices.collect{|inv| [inv.long_name, inv.id]}, params[:move_to_invoice_id].to_i ) ) %> <% else -%>

We're sorry, but no un-published invoices were available in the database for this move.

<% end -%> -

This activity's client and invoice association will be matched with the selected destination.

+

This activity's client and invoice association will be matched with the selected destination. If "(None)" is selected, this actvity will be removed from its current invoice, and placed back in the unassigned activity queue.

<%= submit_tag 'Move...', :class => "MB_focusable" %> or diff --git a/app/views/admin/draft_invoices/batch_create.html.erb b/app/views/admin/draft_invoices/batch_create.html.erb index e46224a..89353ab 100644 --- a/app/views/admin/draft_invoices/batch_create.html.erb +++ b/app/views/admin/draft_invoices/batch_create.html.erb @@ -3,11 +3,11 @@ <%= form_remote_tag( :url => url_for(:action => :batch_create), :after => [ - "$('#{loading_indicator_id(:action => :batch_create, :id => params[:id])}').style.visibility = 'visible'", + "$('#{loading_indicator_id(:action => :batch_create)}').style.visibility = 'visible'", "Form.disable('#{element_form_id(:action => :batch_create)}')" ].join(';'), :complete => [ - "$('#{loading_indicator_id(:action => :batch_create, :id => params[:id])}').style.visibility = 'hidden'", + "$('#{loading_indicator_id(:action => :batch_create)}').style.visibility = 'hidden'", "Form.enable('#{element_form_id(:action => :batch_create)}')" ].join(';'), :failure => "ActiveScaffold.report_500_response('#{active_scaffold_id}')", @@ -62,7 +62,7 @@

diff --git a/app/views/admin/draft_invoices/batch_create.js.rjs b/app/views/admin/draft_invoices/batch_create.js.rjs new file mode 100644 index 0000000..c8f6f30 --- /dev/null +++ b/app/views/admin/draft_invoices/batch_create.js.rjs @@ -0,0 +1,5 @@ +form = element_form_id(:action => :batch_create) +cancel_selector = "##{form} a.cancel".to_json + +page << "$$(#{cancel_selector}).first().link.close();" +page.replace_html active_scaffold_content_id, :partial => 'list', :layout => false if @new_invoices diff --git a/config/environment.rb b/config/environment.rb index dfe2a53..2b54718 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -35,4 +35,4 @@ end -ActionMailer::Base.delivery_method = :sendmail \ No newline at end of file +ActionMailer::Base.delivery_method = :sendmail diff --git a/test/unit/invoice_test.rb b/test/unit/invoice_test.rb index 3efda12..d37d8eb 100644 --- a/test/unit/invoice_test.rb +++ b/test/unit/invoice_test.rb @@ -461,7 +461,56 @@ def test_activity_move assert_raise(StandardError) { material.activity.move_to_invoice invoice_src } end - + + def test_activity_unassign + client_src = Factory.create_client + + create_act_args = {:occurred_on => (DateTime.now << 1), :client => client_src} + + labor = Factory.create_labor( {}, create_act_args.merge({:cost => 1.99}) ) + material = Factory.create_material( {}, create_act_args.merge({:cost => 100.0, :tax => 2.0})) + proposal = Factory.create_proposal( {}, create_act_args) + adjustment = Factory.create_adjustment( {}, create_act_args.merge({:tax => 26.00})) + + subactivities = [labor, material, proposal, adjustment] + + present_date = DateTime.now + + invoice_src = Invoice.create!( + :client => client_src, + :issued_on => present_date, + :activity_types => @activity_types, + :activities => Invoice.recommended_activities_for(client_src, present_date, @activity_types) + ) + + assert_equal 1650.00, invoice_src.amount + assert_equal 48.01, invoice_src.taxes_total + + assert_nothing_raised do + material.activity.move_to_invoice nil + end + + + invoice_src.activities(true) + + material = Activity::Material.find(material.id) + + puts "Material:"+material.activity.inspect + +puts "invoice:" +invoice_src.activities(true).each{|a| + puts "a(%d) : %s %s" % [a.id, a.cost.to_s, a.tax.to_s] +} + + assert_equal 1548.0, invoice_src.amount(true) + assert_equal 46.01, invoice_src.taxes_total + + assert_equal nil, material.activity.invoice_id + assert_equal client_src.id, material.activity.client_id + + end + + private def set_published(inv, published_state)