Class: StatementOfAccount

Inherits:
ApplicationRecord show all
Includes:
Models::AccountingDocumentTransmittable, Models::Auditable
Defined in:
app/models/statement_of_account.rb

Overview

== Schema Information

Table name: statement_of_accounts
Database name: primary

id :integer not null, primary key
currency :string(255)
open_amount :decimal(12, 2)
transmission_error :text
transmission_state :string(255)
uploads_count :integer
created_at :datetime
updated_at :datetime
customer_id :integer

Indexes

index_statement_of_accounts_on_customer_id (customer_id)
index_statement_of_accounts_on_transmission_state (transmission_state)

Constant Summary

Constants included from Models::Auditable

Models::Auditable::ALWAYS_IGNORED

Constants included from Schedulable

Schedulable::SIMPLE_FORM_OPTIONS

Instance Attribute Summary collapse

Belongs to collapse

Methods included from Models::Auditable

#creator, #updater

Has many collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Models::AccountingDocumentTransmittable

#can_be_transmitted?, #fallback_notification_channel_type, #notification_channel_sort_order, #notification_channel_types, #notification_channels, #own_notification_channel_type, #post_communication_exception_hook, #post_communication_sent_hook, #primary_transmission_contact, #primary_transmission_contact_point_id, #transmission_contact_points

Methods included from Models::Auditable

#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record

Methods inherited from ApplicationRecord

ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation

Methods included from Schedulable

config

Methods included from Models::AfterCommittable

#after_commit

Methods included from Models::EventPublishable

#publish_event

Instance Attribute Details

#customer_idObject (readonly)



31
# File 'app/models/statement_of_account.rb', line 31

validates :customer_id, presence: true

Class Method Details

.generate_monthly_statementsObject



105
106
107
108
109
110
# File 'app/models/statement_of_account.rb', line 105

def self.generate_monthly_statements
  customer_ids = Customer.where(send_statement: true).ids
  customer_ids.each do |customer_id|
    StatementOfAccountGenerationWorker.perform_async(customer_id)
  end
end

.generate_pdf(customer, split_by_currency = false) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'app/models/statement_of_account.rb', line 63

def self.generate_pdf(customer, split_by_currency = false)
  results = StatementOfAccount.results(customer, true)
  uploads = []
  if split_by_currency == true
    # need to generate a statement for each currency
    results.each do |currency, res|
      if res.empty?
        nil
      else
        soa = StatementOfAccount.create(currency:, customer_id: customer.id, open_amount: res.sum { |r| BigDecimal(r.open_amount) })
        soa.transmit
        pdf = Statement::PdfGenerator.new.process(soa, { currency => res }).pdf
        path = Upload.temp_location(soa.file_name)
        File.open(path, 'wb') do |file|
          file.write pdf
          file.flush
          file.fsync
        end
        upload = Upload.uploadify(path, 'statement_of_account_pdf', soa, soa.file_name(true))
        uploads << upload
      end
    end
  elsif results.empty?
    # need to combine into one statement
    soa = nil
  else
    soa = StatementOfAccount.create(currency: 'ALL', customer_id: customer.id, open_amount: results.sum { |_currency, res| res.sum { |r| BigDecimal(r.open_amount) } })
    soa.transmit
    pdf = Statement::PdfGenerator.new.process(soa, results).pdf
    path = Upload.temp_location(soa.file_name)
    File.open(path, 'wb') do |file|
      file.write pdf
      file.flush
      file.fsync
    end
    upload = Upload.uploadify(path, 'statement_of_account_pdf', soa, soa.file_name(true))
    uploads << upload
  end

  soa
end

.results(customer, include_ship_to = false) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'app/models/statement_of_account.rb', line 45

def self.results(customer, include_ship_to = false)
  start_date = Date.current - 4.years
  end_date = Date.current + 1.year
  invoices = Invoice.where(state: 'unpaid').where(due_date: start_date..end_date).where.not(total: 0)
                    .select("customer_id, billing_customer_id, 'INVOICE' as doc_type, reference_number, po_number, terms, gl_date, due_date, (invoices.total - coalesce((select sum(rd.amount)+sum(rd.discount)+sum(rd.write_off) as receipts_total from receipt_details rd where rd.state <> 'voided' and rd.invoice_id = invoices.id),0)) as open_amount, currency")
  invoices = include_ship_to == true ? invoices.where.any_of({ billing_customer_id: customer.id }, { customer_id: customer.id }) : invoices.where(billing_customer_id: customer.id)
  credit_memos = CreditMemo.where(state: %w[printed partially_offset]).where(document_date: start_date..end_date).where.not(total: 0)
                           .select("customer_id, billing_customer_id, 'CREDIT' as doc_type, reference_number, original_po_number as po_number, (select p.terms from parties p where p.id = credit_memos.customer_id) as terms, gl_date, document_date as due_date, credit_memos.total - (coalesce((select sum(amount) from receipt_details where credit_memo_id = credit_memos.id and state <> 'voided'),0)-coalesce((select sum(amount) from outgoing_payment_items where credit_memo_id = credit_memos.id and state = 'applied'),0)) as open_amount, currency")
  credit_memos = include_ship_to == true ? credit_memos.where.any_of({ billing_customer_id: customer.id }, { customer_id: customer.id }) : credit_memos.where(billing_customer_id: customer.id)
  receipts = Receipt.where(state: %w[unapplied partially_applied]).where(receipt_date: start_date..end_date).where(customer_id: customer.id).where.not(amount: 0)
                    .select("customer_id, customer_id as billing_customer_id, 'PAYMENT' as doc_type, reference as reference_number, null as po_number, (select p.terms from parties p where p.id = receipts.customer_id) as terms, gl_date as gl_date, receipt_date as due_date, (receipts.amount - coalesce((select sum(rd.amount)+sum(rd.discount)+sum(rd.write_off) as receipts_total from receipt_details rd where rd.state <> 'voided' and rd.receipt_id = receipts.id),0)) * -1 as open_amount, currency")
  statement_results = invoices + credit_memos + receipts
  statement_results = statement_results.group_by(&:currency)
  sorted_statement_results = {}
  statement_results.each { |currency, results| sorted_statement_results[currency] = results.sort_by { |a| Date.strptime(a.due_date.to_s, '%Y-%m-%d') } }
  sorted_statement_results
end

Instance Method Details

#billing_address_idObject



41
42
43
# File 'app/models/statement_of_account.rb', line 41

def billing_address_id
  customer.billing_address.party_id
end

#billing_customerObject



37
38
39
# File 'app/models/statement_of_account.rb', line 37

def billing_customer
  customer.billing_address.party
end

#communicationsActiveRecord::Relation<Communication>

Returns:

See Also:



29
# File 'app/models/statement_of_account.rb', line 29

has_many :communications, -> { order(:id).reverse_order }, as: :resource, dependent: :nullify

#customerCustomer

Returns:

See Also:



26
# File 'app/models/statement_of_account.rb', line 26

belongs_to :customer, optional: true

#file_name(with_extension = true) ⇒ Object



116
117
118
# File 'app/models/statement_of_account.rb', line 116

def file_name(with_extension = true)
  "Statement_of_Account_#{customer.id}_#{currency}#{'.pdf' if with_extension}"
end

#reference_numberObject



112
113
114
# File 'app/models/statement_of_account.rb', line 112

def reference_number
  "SOA#{id}"
end

#to_sObject



33
34
35
# File 'app/models/statement_of_account.rb', line 33

def to_s
  "Statement Of Account #{id}"
end

#uploadsActiveRecord::Relation<Upload>

Returns:

  • (ActiveRecord::Relation<Upload>)

See Also:



28
# File 'app/models/statement_of_account.rb', line 28

has_many :uploads, as: :resource, dependent: :destroy