class Invoice < ActiveRecord::Base belongs_to :user belongs_to :payment has_many :invoicedetails belongs_to :tax, :dependent => :destroy before_destroy :check_send after_destroy :increase_user_balance def check_send if invoice_was_send? errors.add(:send, _("Cannot_delete_Invoice_that_was_send")) return false end end def increase_user_balance # we should _decrease_ user's balance by payments amount, because it is deleted and user should owe more (because there are no payment) user = self.user payment = self.payment if payment user.balance -= payment.amount user.save payment.destroy end Action.add_action(User.current, "invoice_deleted", user.id.to_s) end def invoice_was_send? (sent_email == 1 or sent_manually == 1) and Confline.get_value("Invoice_allow_recalculate_after_send").to_i == 0 end def price_with_tax(options = {}) if options[:ex] if tax tax.apply_tax(converted_price(options[:ex]), options) else if options[:precision] format("%.#{options[:precision].to_i}f",converted_price_with_vat(options[:ex])).to_f else converted_price_with_vat(options[:ex]) end end else if tax tax.apply_tax(price, options) else if options[:precision] format("%.#{options[:precision].to_i}f",price_with_vat).to_f else price_with_vat end end end end def tax_amount(options ={}) if options[:ex] tax.count_tax_amount(converted_price(options[:ex]), options) else tax.count_tax_amount(price, options) end end def calls_price price = 0.0 for invd in self.invoicedetails price += invd.price if invd.invdet_type == 0 end price end def Invoice.filename(user, type, long_name, file_type) temp = (type == "prepaid" ? "Prepaid_" : "") use_short = Confline.get_value("#{temp}Invoice_Short_File_Name", user.owner_id).to_i use_short == 1 ? "#{user.first_name}_#{user.last_name}.#{file_type}" : "#{long_name}.#{file_type}" end def paid?; paid == 1; end # converted attributes for user in current user currency def price b = read_attribute(:price) b.to_f * User.current.currency.exchange_rate.to_f end def price_with_vat b = read_attribute(:price_with_vat) b.to_f * User.current.currency.exchange_rate.to_f end # converted attributes for user in given currency exrate def converted_price(exr) b = read_attribute(:price) b.to_f * exr.to_f end # converted attributes for user in given currency exrate def converted_price_with_vat(exr) b = read_attribute(:price_with_vat) b.to_f * exr.to_f end =begin List of invoice financial data grouped by tryer status. should not be coding application logic to query(IF(paid=...)), but since i dont like db structure the way it is.. *Params* +owner_id+ owner of users that the user is interested in, but might be nil if current user if ordinary user +user_id+ user that has invoices generated for him, might be nil if admin, reseller or accountatn is not interested i certain user, but interested in all his users. BUT IF we are generating financial statemens for ordinary users, they cannot see other users information and must supply theyr own id +status+ valid status parameter would be 'paid' 'unpaid' or 'all', might be nil in that case all statuses would be selected +from_date, till_date+ dates as strings +ordinary_user+ if user is of type 'user' there is no need to join users table, but user_id mus be specified. *Returns* +invoices+ array or smht iterable of Invoice instances, that has count, price, price_with_vat and paid methods =end def self.financial_statements(owner_id, user_id, status, from_date, till_date, ordinary_user=true) #if user not is of type 'user' he must supply user_id. or else invalid params are supplied if ordinary_user and not user_id raise "invalid parameters, 'user' must supply his own id" end condition = ["issue_date BETWEEN '#{from_date}' AND '#{till_date}'"] join = "JOIN taxes ON taxes.id = invoices.tax_id " if not ordinary_user join << "JOIN users ON users.id = invoices.user_id" condition << "owner_id = #{owner_id}" end condition << "user_id = #{user_id}" if user_id and user_id != 'all' if status != 'all' and ['paid', 'unpaid'].include? status condition << "paid = #{status == 'paid' ? 1 : 0}" end Struct.new('We', :count, :price, :price_with_vat, :status) paid = Struct::We.new(0, 0, 0, 'paid') unpaid = Struct::We.new(0, 0, 0, 'unpaid') invoices = Invoice.find(:all, :joins => join, :conditions => condition.join(" AND ")) if invoices.size > 0 invoices.each do |invoice| if invoice.paid? paid.price_with_vat += invoice.price_with_tax paid.price += invoice.price paid.count += 1 else unpaid.price_with_vat += invoice.price_with_tax unpaid.price += invoice.price unpaid.count += 1 end end end return paid, unpaid invoices = Invoice.find_by_sql(query) end end