Skip to content

Instantly share code, notes, and snippets.

@cored
Created December 23, 2019 18:59
Show Gist options
  • Save cored/c0efcbea457ce503e2d1447f65fa8b5a to your computer and use it in GitHub Desktop.
Save cored/c0efcbea457ce503e2d1447f65fa8b5a to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
module Billing
module Models
class InvoiceItem < ActiveRecord::Base
extend Memoist
include Mixins::Reportable
include Phobos::Checkr::Producer
validates_uniqueness_of :report_id, scope: :invoice_id
belongs_to :invoice
delegate :start_date, :end_date, to: :invoice
attribute :program_name, :string
FEE_TYPES = %i[
county_fees
county_service_fees
dmv_fees
service_fees
state_fees
state_service_fees
education_fees
employment_service_fees
international_education_service_fees
international_employment_service_fees
motor_vehicle_report_service_fees
drug_screening_surcharges
health_screening_surcharges
pointer_criminal_state_fees
pointer_state_criminal_service_fees
municipal_court_fees
municipal_service_fees
].freeze
FEE_TYPES.each do |fee_type|
scope "zero_#{fee_type}".to_sym, -> { where(fee_type => 0) }
scope "non_zero_#{fee_type}".to_sym, -> { where.not(fee_type => 0) }
end
scope :zero_fees, lambda {
FEE_TYPES[1..-1].inject(send("zero_#{FEE_TYPES[0]}")) do |chain, fee_type|
chain.send("zero_#{fee_type}")
end
}
scope :non_zero_fees, lambda {
FEE_TYPES[1..-1].inject(send("non_zero_#{FEE_TYPES[0]}")) do |chain, fee_type|
chain.send(:or, send("non_zero_#{fee_type}"))
end
}
def self.invoice!(account_id:, year:, month:, report_id:)
publish(
topic: Handlers::InvoiceItemHandler::TOPIC_NAME,
payload: {
account_id: account_id,
month: month,
year: year,
report_id: report_id
}.to_json,
partition_key: "#{account_id}-#{year}-#{month}-#{report_id}"
)
end
def events
@events ||= Event.where(
invoice_date: start_date..end_date,
report_id: report_id
).to_a.uniq(&:signature).sort_by { |e| -e.context_date.to_i }
end
def package_setting
invoice.find_package(report.package_id)
end
memoize :package_setting
def applicant_pay?
!!package_setting&.try(:[], :applicant_pay?)
end
def price_events!
events.reverse_each do |event|
event.amount = Pricing.price_event(event, invoice)
event.save(validate: false)
end
end
def summarize!
item_summary = Summary.new(events)
self.summary = item_summary.counts
FEE_TYPES.each do |fee_type|
send("#{fee_type}=", item_summary.totals[fee_type])
end
self.total_amount = item_summary.totals[:all]
end
def aggregate_summary
summary.reject do |category, _labels|
skippable_category?(category)
end
end
def skippable_category?(category)
%w[events reports].include? category
end
def fill_extra_fields!
fill_candidate!
fill_report!
self.csv = generate_csv
end
def fill_candidate!
return unless candidate
self.candidate_custom_id = candidate.custom_id
self.candidate_name = candidate.name
self.candidate_geo_id = candidate.geo_id
self.candidate_geo_name = candidate.geo_name
end
def fill_report!
self.alias_count = calculate_alias_count
self.program_name = package_setting&.try(:[], :program_name)
self.package_title = retrieve_package_title
self.cost_center = retrieve_cost_center
self.segment_stamps = retrieve_segment_stamps
self.report_completed_at = completed_at
self.report_created_at = created_at
self.report_upgraded_at = upgraded_at
self.report_revised_at = revised_at
self.report_account_name = account_name
end
def generate_csv
Billing::Invoices::CSV::HEADERS.keys.map do |attribute|
value = case attribute
when :state_fees then pointer_and_state_fees
when :state_service_fees then pointer_and_state_service_fees
else public_send(attribute)
end
attribute_value_to_csv(attribute, value)&.to_s
end
end
def pointer_and_state_fees
[
public_send(:state_fees),
public_send(:pointer_criminal_state_fees)
].compact.sum
end
def pointer_and_state_service_fees
[
public_send(:state_service_fees),
public_send(:pointer_state_criminal_service_fees)
].compact.sum
end
def attribute_value_to_csv(attribute, value)
return value if attribute == :alias_count
return value / 100.0 if value.to_f == value
return nil if value.nil?
return "\"#{value}\"" if attribute == :candidate_custom_id
value
end
def account_name
subaccounts = invoice.account_settings.fetch('subaccounts', {})
account = subaccounts[final_event.account_id] unless subaccounts.empty?
account ||= invoice.account_settings
account.fetch('name')
end
def report
@report ||= Report.find(report_id)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment