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