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.

Revisions

  1. cored created this gist Dec 23, 2019.
    190 changes: 190 additions & 0 deletions invoice_item.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,190 @@
    # 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