[#4410] Replace Payment Terms with an Enumeration
Instead of using a hard coded value for Payment Terms, they will use Redmine's Enumeration table. This provides an admin gui to managing the value as well as ordering them.
This commit is contained in:
@@ -75,6 +75,6 @@ module ContractsHelper
|
||||
|
||||
def format_payment_terms(value)
|
||||
return '' if value.blank?
|
||||
return l(Contract::PaymentTerms[value.to_sym])
|
||||
return h(value.name)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,6 +4,7 @@ class Contract < ActiveRecord::Base
|
||||
# Associations
|
||||
belongs_to :project
|
||||
belongs_to :account_executive, :class_name => 'User', :foreign_key => 'account_executive_id'
|
||||
belongs_to :payment_term, :class_name => "PaymentTerm", :foreign_key => "payment_term_id"
|
||||
has_many :deliverables, :dependent => :destroy
|
||||
|
||||
# Validations
|
||||
@@ -24,7 +25,7 @@ class Contract < ActiveRecord::Base
|
||||
attr_accessible :billable_rate
|
||||
attr_accessible :discount
|
||||
attr_accessible :discount_note
|
||||
attr_accessible :payment_terms
|
||||
attr_accessible :payment_term_id
|
||||
attr_accessible :client_ap_contact_information
|
||||
attr_accessible :po_number
|
||||
attr_accessible :client_point_of_contact
|
||||
@@ -91,19 +92,6 @@ class Contract < ActiveRecord::Base
|
||||
end
|
||||
alias_method :profit_spent, :profit_left
|
||||
|
||||
PaymentTerms = {
|
||||
:net_0 => :text_payment_terms_net_0,
|
||||
:net_15 => :text_payment_terms_net_15,
|
||||
:net_30 => :text_payment_terms_net_30,
|
||||
:net_45 => :text_payment_terms_net_45
|
||||
}
|
||||
|
||||
def payment_terms_for_select
|
||||
PaymentTerms.collect {|value, label|
|
||||
[l(label), value.to_s]
|
||||
}
|
||||
end
|
||||
|
||||
def after_initialize
|
||||
self.executed = false unless self.executed.present?
|
||||
end
|
||||
|
||||
19
app/models/payment_term.rb
Normal file
19
app/models/payment_term.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
class PaymentTerm < Enumeration
|
||||
unloadable
|
||||
|
||||
has_many :contracts, :foreign_key => 'payment_term_id'
|
||||
|
||||
OptionName = :enumeration_payment_term
|
||||
|
||||
def option_name
|
||||
OptionName
|
||||
end
|
||||
|
||||
def objects_count
|
||||
contracts.count
|
||||
end
|
||||
|
||||
def transfer_relations(to)
|
||||
contracts.update_all("payment_term_id = #{to.id}")
|
||||
end
|
||||
end
|
||||
@@ -18,7 +18,7 @@
|
||||
<% end %>
|
||||
|
||||
<% form.inputs :name => l(:text_account_legend) do %>
|
||||
<%= form.input :payment_terms, :as => :select, :collection => resource.payment_terms_for_select %>
|
||||
<%= form.input :payment_term %>
|
||||
<%= form.input :po_number %>
|
||||
<%= form.input :client_ap_contact_information, :input_html => {:class => 'wiki-edit', :rows => '5'} %>
|
||||
<%= form.input :client_point_of_contact, :input_html => {:class => 'wiki-edit', :rows => '5'} %>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<%= show_field(resource, :client_point_of_contact, :format => :textilizable, :raw => true, :html_options => {:class => 'contract-client-point-of-contact padd'}, :label_html_options => {:width => '25%'}) %>
|
||||
<%= show_field(resource, :executed, :html_options => {:class => 'contract-executed'}) %>
|
||||
<%= show_field(resource, :discount_note, :format => :textilizable, :raw => true, :html_options => {:class => 'contract-discount-note'}) %>
|
||||
<%= show_field(resource, :payment_terms, :format => :format_payment_terms, :html_options => {:class => 'contract-payment-terms'}) %>
|
||||
<%= show_field(resource, :payment_term, :format => :format_payment_terms, :html_options => {:class => 'contract-payment-terms'}) %>
|
||||
<%= show_field(resource, :client_ap_contact_information, :format => :textilizable, :raw => true, :html_options => {:class => 'contract-client-ap-contact-information'}) %>
|
||||
<%= show_field(resource, :po_number, :html_options => {:class => 'contract-po-number'}) %>
|
||||
<%= show_field(resource, :details, :format => :textilizable, :raw => true, :html_options => {:class => 'contract-details'}) %>
|
||||
|
||||
@@ -13,14 +13,10 @@ en:
|
||||
field_discount: "Discount"
|
||||
field_discount_hint: "$, %"
|
||||
field_discount_note: "Discounts Notes"
|
||||
field_payment_terms: "Payment Terms"
|
||||
field_payment_term: "Payment Terms"
|
||||
field_client_ap_contact_information: "AP Contact Info"
|
||||
field_po_number: "PO Number"
|
||||
field_details: "Details"
|
||||
text_payment_terms_net_0: "Net 0"
|
||||
text_payment_terms_net_15: "Net 15"
|
||||
text_payment_terms_net_30: "Net 30"
|
||||
text_payment_terms_net_45: "Net 45"
|
||||
button_add_new: Add New
|
||||
text_new_deliverable: New Deliverable
|
||||
text_edit_deliverable_title: "Edit {{title}}"
|
||||
@@ -60,4 +56,5 @@ en:
|
||||
text_account_legend: "Account Management"
|
||||
text_deliverable_details_legend: "Deliverable Details"
|
||||
text_save_contract: "Save Contract"
|
||||
enumeration_payment_term: "Payment Terms"
|
||||
|
||||
|
||||
9
db/migrate/008_add_payment_term_id_to_contracts.rb
Normal file
9
db/migrate/008_add_payment_term_id_to_contracts.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
class AddPaymentTermIdToContracts < ActiveRecord::Migration
|
||||
def self.up
|
||||
add_column :contracts, :payment_term_id, :integer
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_column :contracts, :payment_term_id
|
||||
end
|
||||
end
|
||||
9
db/migrate/009_remove_payment_terms_from_contracts.rb
Normal file
9
db/migrate/009_remove_payment_terms_from_contracts.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
class RemovePaymentTermsFromContracts < ActiveRecord::Migration
|
||||
def self.up
|
||||
remove_column :contracts, :payment_terms
|
||||
end
|
||||
|
||||
def self.down
|
||||
add_column :contracts, :payment_terms, :string
|
||||
end
|
||||
end
|
||||
14
db/migrate/010_populate_payment_terms.rb
Normal file
14
db/migrate/010_populate_payment_terms.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
class PopulatePaymentTerms < ActiveRecord::Migration
|
||||
def self.up
|
||||
[0, 15, 30, 45, 60, 75, 90].each_with_index do |days, index|
|
||||
name = "Net #{days}"
|
||||
unless PaymentTerm.find_by_name(name)
|
||||
PaymentTerm.create!(:name => name, :position => index + 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
# No-op
|
||||
end
|
||||
end
|
||||
2
init.rb
2
init.rb
@@ -59,6 +59,8 @@ Dispatcher.to_prepare :redmine_contracts do
|
||||
Formtastic::SemanticFormBuilder.all_fields_required_by_default = false
|
||||
Formtastic::SemanticFormBuilder.required_string = "<span class='required'> *</span>"
|
||||
|
||||
require_dependency 'payment_term' # Load so Enumeration will pick up the subclass in dev
|
||||
|
||||
require_dependency 'project'
|
||||
Project.send(:include, RedmineContracts::Patches::ProjectPatch)
|
||||
require_dependency 'issue'
|
||||
|
||||
@@ -5,7 +5,7 @@ class ContractsDeleteTest < ActionController::IntegrationTest
|
||||
|
||||
def setup
|
||||
@project = Project.generate!(:identifier => 'main')
|
||||
@contract = Contract.generate!(:project => @project, :name => 'A Contract', :payment_terms => 'net_15')
|
||||
@contract = Contract.generate!(:project => @project, :name => 'A Contract')
|
||||
end
|
||||
|
||||
should "allow admins to delete the contract" do
|
||||
|
||||
@@ -8,7 +8,7 @@ class ContractsEditTest < ActionController::IntegrationTest
|
||||
@account_executive = User.generate!
|
||||
@role = Role.generate!
|
||||
User.add_to_project(@account_executive, @project, @role)
|
||||
@contract = Contract.generate!(:project => @project, :name => 'A Contract', :payment_terms => 'net_15', :account_executive => @account_executive)
|
||||
@contract = Contract.generate!(:project => @project, :name => 'A Contract', :account_executive => @account_executive)
|
||||
end
|
||||
|
||||
should "allow any user to edit the contract" do
|
||||
@@ -23,9 +23,7 @@ class ContractsEditTest < ActionController::IntegrationTest
|
||||
assert_select "h2", :text => /#{@contract.name}/
|
||||
assert_select "form#edit_contract_#{@contract.id}.contract" do
|
||||
assert_select "input[value=?]", /#{@contract.name}/
|
||||
assert_select "select#contract_payment_terms" do
|
||||
assert_select "option[selected=selected][value=net_15]"
|
||||
end
|
||||
assert_select "select#contract_payment_term_id"
|
||||
end
|
||||
|
||||
fill_in "Name", :with => 'An updated name'
|
||||
|
||||
@@ -5,6 +5,8 @@ class ContractsNewTest < ActionController::IntegrationTest
|
||||
|
||||
def setup
|
||||
@project = Project.generate!(:identifier => 'main')
|
||||
PaymentTerm.generate!(:type => 'PaymentTerm', :name => 'Net 15')
|
||||
PaymentTerm.generate!(:type => 'PaymentTerm', :name => 'Net 30')
|
||||
end
|
||||
|
||||
should "allow any user to open the new contracts form" do
|
||||
@@ -40,7 +42,7 @@ class ContractsNewTest < ActionController::IntegrationTest
|
||||
assert_equal @account_executive, @contract.account_executive
|
||||
assert_equal '2010-01-01', @contract.start_date.to_s
|
||||
assert_equal '2010-12-31', @contract.end_date.to_s
|
||||
assert_equal 'net_30', @contract.payment_terms
|
||||
assert_equal 'Net 30', @contract.payment_term.name
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ class DeliverablesDeleteTest < ActionController::IntegrationTest
|
||||
|
||||
def setup
|
||||
@project = Project.generate!(:identifier => 'main')
|
||||
@contract = Contract.generate!(:project => @project, :name => 'A Contract', :payment_terms => 'net_15')
|
||||
@contract = Contract.generate!(:project => @project, :name => 'A Contract')
|
||||
@manager = User.generate!
|
||||
@deliverable = FixedDeliverable.generate!(:contract => @contract, :manager => @manager)
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ class DeliverablesEditTest < ActionController::IntegrationTest
|
||||
|
||||
def setup
|
||||
@project = Project.generate!(:identifier => 'main')
|
||||
@contract = Contract.generate!(:project => @project, :name => 'A Contract', :payment_terms => 'net_15')
|
||||
@contract = Contract.generate!(:project => @project, :name => 'A Contract')
|
||||
@manager = User.generate!
|
||||
@role = Role.generate!
|
||||
User.add_to_project(@manager, @project, @role)
|
||||
|
||||
@@ -3,7 +3,7 @@ require 'test_helper'
|
||||
class OverheadPluginIntegrationTest < ActionController::IntegrationTest
|
||||
def setup
|
||||
@project = Project.generate!(:identifier => 'main')
|
||||
@contract = Contract.generate!(:project => @project, :name => 'A Contract', :payment_terms => 'net_15')
|
||||
@contract = Contract.generate!(:project => @project, :name => 'A Contract')
|
||||
@manager = User.generate!
|
||||
@role = Role.generate!
|
||||
User.add_to_project(@manager, @project, @role)
|
||||
|
||||
@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + '/../test_helper'
|
||||
class ContractTest < ActiveSupport::TestCase
|
||||
should_belong_to :account_executive
|
||||
should_belong_to :project
|
||||
should_belong_to :payment_term
|
||||
should_have_many :deliverables
|
||||
|
||||
should_validate_presence_of :name
|
||||
|
||||
40
test/unit/payment_term_test.rb
Normal file
40
test/unit/payment_term_test.rb
Normal file
@@ -0,0 +1,40 @@
|
||||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
|
||||
class PaymentTermTest < ActiveSupport::TestCase
|
||||
include Redmine::I18n
|
||||
|
||||
should_have_many(:contracts)
|
||||
|
||||
should "be a subclass of Enumeration" do
|
||||
assert_equal Enumeration, PaymentTerm.superclass
|
||||
end
|
||||
|
||||
context "#option_name" do
|
||||
should "be Payment Terms" do
|
||||
assert_equal "Payment Terms", l(PaymentTerm.new.option_name)
|
||||
end
|
||||
end
|
||||
|
||||
context "#objects_count" do
|
||||
should "count the number of contracts with this payment term" do
|
||||
@payment_term = PaymentTerm.generate!(:type => 'PaymentTerm')
|
||||
Contract.generate!(:payment_term => @payment_term)
|
||||
Contract.generate!(:payment_term => @payment_term)
|
||||
|
||||
assert_equal 2, @payment_term.objects_count
|
||||
end
|
||||
end
|
||||
|
||||
context "#transfer_relations" do
|
||||
should "update all contracts to use a new PaymentTerm" do
|
||||
@old_payment_term = PaymentTerm.generate!(:type => 'PaymentTerm')
|
||||
@new_payment_term = PaymentTerm.generate!(:type => 'PaymentTerm')
|
||||
@contract1 = Contract.generate!(:payment_term => @old_payment_term)
|
||||
@contract2 = Contract.generate!(:payment_term => @old_payment_term)
|
||||
|
||||
@old_payment_term.transfer_relations(@new_payment_term)
|
||||
assert_equal @new_payment_term, @contract1.reload.payment_term
|
||||
assert_equal @new_payment_term, @contract2.reload.payment_term
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user