app/models/dorsale/billing_machine/quotation.rb in dorsale-3.0.3 vs app/models/dorsale/billing_machine/quotation.rb in dorsale-3.1.0
- old
+ new
@@ -1,189 +1,131 @@
-module Dorsale
- module BillingMachine
- class Quotation < ActiveRecord::Base
- self.table_name = "dorsale_billing_machine_quotations"
+class Dorsale::BillingMachine::Quotation < ActiveRecord::Base
+ self.table_name = "dorsale_billing_machine_quotations"
- STATES = %w(pending accepted refused canceled)
+ STATES = %w(pending accepted refused canceled)
- belongs_to :customer, polymorphic: true
- belongs_to :id_card
- belongs_to :payment_term
- has_many :lines,
- :inverse_of => :quotation,
- :dependent => :destroy,
- :class_name => ::Dorsale::BillingMachine::QuotationLine
+ belongs_to :customer, polymorphic: true
+ belongs_to :id_card
+ belongs_to :payment_term
+ has_many :lines,
+ :inverse_of => :quotation,
+ :dependent => :destroy,
+ :class_name => ::Dorsale::BillingMachine::QuotationLine
- has_many :attachments,
- :as => :attachable,
- :dependent => :destroy,
- :class_name => ::Dorsale::Alexandrie::Attachment
+ has_many :attachments,
+ :as => :attachable,
+ :dependent => :destroy,
+ :class_name => ::Dorsale::Alexandrie::Attachment
- accepts_nested_attributes_for :lines, allow_destroy: true
+ accepts_nested_attributes_for :lines, allow_destroy: true
- polymorphic_id_for :customer
+ polymorphic_id_for :customer
- validates :id_card, presence: true
- validates :date, presence: true
- validates :state, presence: true, inclusion: {in: STATES}
+ validates :id_card, presence: true
+ validates :date, presence: true
+ validates :state, presence: true, inclusion: {in: STATES}
- # simple_form
- validates :id_card_id, presence: true
+ default_scope -> {
+ order(unique_index: :desc)
+ }
- def initialize(*)
- super
- self.state = STATES.first if state.nil?
- self.date = Time.zone.now.to_date if date.nil?
- assign_default_values
- end
+ def initialize(*)
+ super
+ self.state = STATES.first if state.nil?
+ self.date = Time.zone.now.to_date if date.nil?
+ assign_default_values
+ end
- before_create :assign_unique_index
- before_create :assign_tracking_id
- before_validation :assign_default_values
+ before_create :assign_unique_index
+ before_create :assign_tracking_id
+ before_validation :assign_default_values
- def assign_unique_index
- if unique_index.nil?
- self.unique_index = self.class.all.pluck(:unique_index).max.to_i.next
- end
- end
+ def assign_unique_index
+ if unique_index.nil?
+ self.unique_index = self.class.all.pluck(:unique_index).max.to_i.next
+ end
+ end
- def assign_tracking_id
- self.tracking_id = date.year.to_s + "-" + unique_index.to_s.rjust(2, "0")
- end
+ def assign_tracking_id
+ self.tracking_id = date.year.to_s + "-" + unique_index.to_s.rjust(2, "0")
+ end
- def assign_default_values
- self.expires_at = date + 1.month if expires_at.nil?
- self.commercial_discount = 0 if commercial_discount.nil?
- self.vat_amount = 0 if vat_amount.nil?
- self.total_excluding_taxes = 0 if total_excluding_taxes
- end
+ def assign_default_values
+ self.expires_at = date + 1.month if expires_at.nil?
+ self.commercial_discount = 0 if commercial_discount.nil?
+ self.vat_amount = 0 if vat_amount.nil?
+ self.total_excluding_taxes = 0 if total_excluding_taxes
+ end
- before_save :update_totals
+ before_save :update_totals
- def update_totals
- assign_default_values
- lines_sum = lines.map(&:total).sum
+ def update_totals
+ assign_default_values
+ lines_sum = lines.map(&:total).sum
- self.total_excluding_taxes = lines_sum - commercial_discount
+ self.total_excluding_taxes = lines_sum - commercial_discount
- if commercial_discount.nonzero? && lines_sum.nonzero?
- discount_rate = commercial_discount / lines_sum
- else
- discount_rate = 0.0
- end
+ if commercial_discount.nonzero? && lines_sum.nonzero?
+ discount_rate = commercial_discount / lines_sum
+ else
+ discount_rate = 0.0
+ end
- self.vat_amount = 0.0
+ self.vat_amount = 0.0
- lines.each do |line|
- line_total = line.total - (line.total * discount_rate)
- self.vat_amount += (line_total * line.vat_rate / 100.0)
- end
+ lines.each do |line|
+ line_total = line.total - (line.total * discount_rate)
+ self.vat_amount += (line_total * line.vat_rate / 100.0)
+ end
- self.total_including_taxes = total_excluding_taxes + vat_amount
- end
+ self.total_including_taxes = total_excluding_taxes + vat_amount
+ end
- def total_excluding_taxes=(*); super; end
- private :total_excluding_taxes=
+ def total_excluding_taxes=(*); super; end
+ private :total_excluding_taxes=
- def vat_amount=(*); super; end
- private :vat_amount=
+ def vat_amount=(*); super; end
+ private :vat_amount=
- def total_including_taxes=(*); super; end
- private :total_including_taxes=
+ def total_including_taxes=(*); super; end
+ private :total_including_taxes=
- def balance
- self.total_including_taxes
- end
+ def balance
+ self.total_including_taxes
+ end
- def vat_rate
- if ::Dorsale::BillingMachine.vat_mode == :multiple
- raise "Quotation#vat_rate is not available in multiple vat mode"
- end
+ def vat_rate
+ if ::Dorsale::BillingMachine.vat_mode == :multiple
+ raise "Quotation#vat_rate is not available in multiple vat mode"
+ end
- return @vat_rate if @vat_rate
+ return @vat_rate if @vat_rate
- vat_rates = lines.map(&:vat_rate).uniq
+ vat_rates = lines.map(&:vat_rate).uniq
- if vat_rates.length > 1
- raise "Quotation has multiple vat rates"
- end
+ if vat_rates.length > 1
+ raise "Quotation has multiple vat rates"
+ end
- vat_rates.first || ::Dorsale::BillingMachine::DEFAULT_VAT_RATE
- end
+ vat_rates.first || ::Dorsale::BillingMachine::DEFAULT_VAT_RATE
+ end
- def vat_rate=(value)
- @vat_rate = value
- end
+ def vat_rate=(value)
+ @vat_rate = value
+ end
- before_validation :apply_vat_rate_to_lines
+ before_validation :apply_vat_rate_to_lines
- def apply_vat_rate_to_lines
- return if ::Dorsale::BillingMachine.vat_mode == :multiple
+ def apply_vat_rate_to_lines
+ return if ::Dorsale::BillingMachine.vat_mode == :multiple
- lines.each do |line|
- line.vat_rate = vat_rate
- end
- end
+ lines.each do |line|
+ line.vat_rate = vat_rate
+ end
+ end
- def pdf
- pdf = ::Dorsale::BillingMachine.quotation_pdf_model.new(self)
- pdf.build
- pdf
- end
-
- def create_copy!
- new_quotation = self.dup
-
- self.lines.each do |line|
- new_quotation.lines << line.dup
- end
-
- new_quotation.unique_index = nil
- new_quotation.created_at = nil
- new_quotation.updated_at = nil
- new_quotation.date = Time.zone.now.to_date
- new_quotation.state = Quotation::STATES.first
-
- new_quotation.save!
-
- self.attachments.each do |attachment|
- new_attachment = attachment.dup
- new_attachment.attachable = new_quotation
- new_attachment.file = File.open(attachment.file.path)
- new_attachment.save!
- end
-
- new_quotation
- end
-
- def to_new_invoice
- new_invoice = Dorsale::BillingMachine::Invoice.new
-
- self.attributes.each do |k, v|
- next if k.to_s == "id"
- next if k.to_s.match /index|tracking|_at/
-
- if new_invoice.respond_to?("#{k}=")
- new_invoice.public_send("#{k}=", v)
- end
- end
-
- self.lines.each do |line|
- new_line = new_invoice.lines.new
- line.attributes.each do |k, v|
- next if k.to_s == "id"
- next if k.to_s.match /index|tracking|_at/
-
- if new_line.respond_to?("#{k}=")
- new_line.public_send("#{k}=", v)
- end
- end
- end
-
- new_invoice.date = Time.zone.now.to_date
-
- new_invoice
- end
-
- end # Quotation
- end # BillingMachine
-end # Dorsale
+ def to_pdf
+ ::Dorsale::BillingMachine.quotation_pdf_model.new(self)
+ .tap(&:build)
+ .render_with_attachments
+ end
+end