Module: Crm::Reports::GrossSalesReportHelper

Defined in:
app/helpers/crm/reports/gross_sales_report_helper.rb

Overview

View helper for the CRM gross sales report
(Crm::Reports::GrossSalesReportController) and related sales reports,
providing variance/growth indicators, number and currency formatting,
and drill-through search links (invoices, activities, customers,
accounting records).

Instance Method Summary collapse

Instance Method Details

#acc_format(value) ⇒ String?

Formats a value in accounting style: thousands separators for positive
values, parenthesized for negative values, nil for zero.

Parameters:

  • value (Numeric, nil)

    value to format

Returns:

  • (String, nil)

    the formatted value, or nil when blank or zero



195
196
197
198
199
200
201
202
203
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 195

def acc_format(value)
  return unless value

  if value.positive?
    value.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
  elsif value.negative?
    "(#{(value * -1).to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse})"
  end
end

Builds a link to the customer search scoped to a tier-2 program pricing
tier (or its exclusion variants) and sales reps, for the account overview.

Parameters:

  • num_customers (Integer)

    pre-computed customer count to display

  • program_pricing_id (Integer)

    tier-2 program pricing ID; 999_998 excludes
    standard catalogs, 999_999 excludes the standard tier IDs

  • sales_rep_ids (Array<Integer>)

    primary sales rep filter (empty means all)

  • style (Integer)

    size preset passed to #query_link

Returns:

  • (ActiveSupport::SafeBuffer)

    the link HTML



488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 488

def acc_ov_customers_link_to(num_customers, program_pricing_id, sales_rep_ids, style)
  pp_ids = [1316, 2422, 2423, 2424, 2425, 582, 583]
  catalogs = Catalog.where("id in (1,2)").ids.sort.uniq
  options = {}
  options[:num_records] = num_customers
  options[:style] = style
  options[:query_params] = {}
  options[:query_params][:catalog_id_in] = catalogs if program_pricing_id != 999_998
  options[:query_params][:catalog_id_not_in] = catalogs if program_pricing_id == 999_998
  options[:query_params][:tier2_program_pricing_id_in] = program_pricing_id if program_pricing_id <= 999_997
  options[:query_params][:tier2_program_pricing_id_not_in] = pp_ids if program_pricing_id == 999_999
  options[:query_params][:primary_sales_rep_id_includes] = sales_rep_ids if sales_rep_ids.any?
  link, = query_link(CustomerSearch, nil, options)
  link.html_safe
end

Builds a path to the accounting-records report for a month scoped to a
company and ledger account.

Parameters:

  • year (Integer)

    report year

  • month (Integer)

    report month

  • company_id (Integer)

    company filter

  • account_id (Integer)

    ledger account filter; <= 4999 selects the income statement

Returns:

  • (String)

    the report path



365
366
367
368
369
370
371
372
373
374
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 365

def accounting_record_link(year, month, company_id, )
  params = {}
  params[:command] = {}
  params[:command][:period1_gteq] = Date.new(year, month)
  params[:command][:period1_lteq] = Date.new(year, month).end_of_month
  params[:command][:company_ids] = [company_id]
  params[:command][:ledger_account_ids] = []
  params[:command][:from_report] =  <= 4999 ? 1 : 2
  reports_accounting_records_path(params)
end

Builds a link to the customer search scoped like
#acc_ov_customers_link_to plus a number-of-offices filter.

Parameters:

  • num_customers (Integer)

    pre-computed customer count to display

  • program_pricing_id (Integer)

    tier-2 program pricing ID; 999_998 excludes
    standard catalogs, 999_999 excludes the standard tier IDs

  • number_of_offices (Integer)

    number of offices filter

  • sales_rep_ids (Array<Integer>)

    primary sales rep filter (empty means all)

  • style (Integer)

    size preset passed to #query_link

Returns:

  • (ActiveSupport::SafeBuffer)

    the link HTML



514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 514

def bo_num_offices_customers_link_to(num_customers, program_pricing_id, number_of_offices, sales_rep_ids, style)
  pp_ids = [1316, 2422, 2423, 2424, 2425, 582, 583]
  catalogs = Catalog.where("id in (1,2)").ids.sort.uniq
  options = {}
  options[:num_records] = num_customers
  options[:style] = style
  options[:query_params] = {}
  options[:query_params][:catalog_id_in] = catalogs if program_pricing_id != 999_998
  options[:query_params][:catalog_id_not_in] = catalogs if program_pricing_id == 999_998
  options[:query_params][:tier2_program_pricing_id_in] = program_pricing_id if program_pricing_id <= 999_997
  options[:query_params][:tier2_program_pricing_id_not_in] = pp_ids if program_pricing_id == 999_999
  options[:query_params][:number_of_offices] = number_of_offices
  options[:query_params][:primary_sales_rep_id_includes] = sales_rep_ids if sales_rep_ids.any?
  link, = query_link(CustomerSearch, nil, options)
  link.html_safe
end

Builds a link to the customer search scoped like
#acc_ov_customers_link_to plus a projects-per-year filter.

Parameters:

  • num_customers (Integer)

    pre-computed customer count to display

  • program_pricing_id (Integer)

    tier-2 program pricing ID; 999_998 excludes
    standard catalogs, 999_999 excludes the standard tier IDs

  • projects (Integer)

    projects-per-year filter

  • sales_rep_ids (Array<Integer>)

    primary sales rep filter (empty means all)

  • style (Integer)

    size preset passed to #query_link

Returns:

  • (ActiveSupport::SafeBuffer)

    the link HTML



541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 541

def bo_projects_customers_link_to(num_customers, program_pricing_id, projects, sales_rep_ids, style)
  pp_ids = [1316, 2422, 2423, 2424, 2425, 582, 583]
  catalogs = Catalog.where("id in (1,2)").ids.sort.uniq
  options = {}
  options[:num_records] = num_customers
  options[:style] = style
  options[:query_params] = {}
  options[:query_params][:catalog_id_in] = catalogs if program_pricing_id != 999_998
  options[:query_params][:catalog_id_not_in] = catalogs if program_pricing_id == 999_998
  options[:query_params][:tier2_program_pricing_id_in] = program_pricing_id if program_pricing_id <= 999_997
  options[:query_params][:tier2_program_pricing_id_not_in] = pp_ids if program_pricing_id == 999_999
  options[:query_params][:projects_per_year] = projects
  options[:query_params][:primary_sales_rep_id_includes] = sales_rep_ids if sales_rep_ids.any?
  link, = query_link(CustomerSearch, nil, options)
  link.html_safe
end

Builds a path to the accounting-records report for a month scoped to a
company, ledger account, and business unit.

Parameters:

  • year (Integer)

    report year

  • month (Integer)

    report month

  • company_id (Integer)

    company filter

  • account_id (Integer)

    ledger account filter

  • bu_id (Integer)

    business unit filter

Returns:

  • (String)

    the report path



385
386
387
388
389
390
391
392
393
394
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 385

def business_units_link(year, month, company_id, , bu_id)
  params = {}
  params[:command] = {}
  params[:command][:period1_gteq] = Date.new(year, month)
  params[:command][:period1_lteq] = Date.new(year, month).end_of_month
  params[:command][:company_ids] = [company_id]
  params[:command][:ledger_account_ids] = []
  params[:command][:business_units_ids] = [bu_id]
  reports_accounting_records_path(params)
end

Builds a link to the closed-activities search for an employee on a date.

Parameters:

  • employee_id (Integer)

    closed-by filter

  • ca_count (Integer)

    pre-computed closed activity count to display

  • date (Date)

    the day the activities were completed on

  • options (Hash) (defaults to: {})

    options forwarded to query_template_link

Options Hash (options):

  • :num_records (Integer)

    pre-computed record count to display

  • :query_params (Hash)

    search filter params for the query template

Returns:

  • (String)

    the link HTML



345
346
347
348
349
350
351
352
353
354
355
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 345

def closed_activities_link_to(employee_id, ca_count, date, options = {})
  options[:num_records] = ca_count
  options[:query_params] = {}
  options[:query_params][:completion_datetime_gteq_time] = date.beginning_of_day
  options[:query_params][:completion_datetime_lteq_time] = date.end_of_day
  options[:query_params][:closed_by_id_in] = [employee_id]
  options[:query_params][:activity_type_id] = ['Any']
  options[:query_params][:activity_result_type_id] = ['AnyCompletion']
  link, = query_template_link(ActivitySearch, nil, options)
  link.html_safe
end

#commission_state(status) ⇒ ActiveSupport::SafeBuffer?

Renders a two-letter commission state badge (IP/PP/PO) colored by status.

Parameters:

  • status (String)

    commission state ('in_progress', 'pending_payout', 'paid_out')

Returns:

  • (ActiveSupport::SafeBuffer, nil)

    the badge HTML, or nil for an unknown status



234
235
236
237
238
239
240
241
242
243
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 234

def commission_state(status)
  case status
  when 'in_progress'
    (:span, 'IP', class: 'badge bg-success')
  when 'pending_payout'
    (:span, 'PP', class: 'badge bg-warning')
  when 'paid_out'
    (:span, 'PO', class: 'badge bg-danger')
  end
end

#comparison_arrow(p1_value, p2_value) ⇒ ActiveSupport::SafeBuffer

Renders a trend arrow comparing two period values, or a '-' span when equal.

Parameters:

  • p1_value (Numeric)

    first (current) period value

  • p2_value (Numeric)

    second (previous) period value

Returns:

  • (ActiveSupport::SafeBuffer)

    the indicator HTML



52
53
54
55
56
57
58
59
60
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 52

def comparison_arrow(p1_value, p2_value)
  if p1_value > p2_value
    fa_icon('arrow-trend-up', family: :solid, class: 'text-success')
  elsif p1_value < p2_value
    fa_icon('arrow-trend-down', family: :solid, class: 'text-danger')
  else
    (:span, '-', class: 'text-body-secondary')
  end
end

#counter_span_current_month(number) ⇒ ActiveSupport::SafeBuffer?

Renders a danger badge with the number when it is positive (current-month
counts).

Parameters:

  • number (Numeric)

    count to display

Returns:

  • (ActiveSupport::SafeBuffer, nil)

    the badge HTML, or nil when not positive



218
219
220
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 218

def counter_span_current_month(number)
  (:span, number, class: 'badge bg-danger') if number.positive?
end

#counter_span_sr(number) ⇒ ActiveSupport::SafeBuffer?

Renders a secondary badge with the number when it is positive.

Parameters:

  • number (Numeric)

    count to display

Returns:

  • (ActiveSupport::SafeBuffer, nil)

    the badge HTML, or nil when not positive



209
210
211
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 209

def counter_span_sr(number)
  (:span, number, class: 'badge bg-secondary') if number.positive?
end

#counter_span_sr_yearly(number) ⇒ ActiveSupport::SafeBuffer

Renders a success badge with the number (yearly sales-rep counts).

Parameters:

  • number (Numeric)

    count to display

Returns:

  • (ActiveSupport::SafeBuffer)

    the badge HTML



226
227
228
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 226

def counter_span_sr_yearly(number)
  (:span, number, class: 'badge bg-success')
end

Builds a link to the customer search for a list of customer IDs.

Parameters:

  • customers_ids (Array<Integer>)

    customer IDs to filter on

  • num_customers (Integer)

    pre-computed customer count to display

  • style (Integer)

    size preset passed to #query_link

Returns:

  • (ActiveSupport::SafeBuffer)

    the link HTML



469
470
471
472
473
474
475
476
477
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 469

def customers_link_to(customers_ids, num_customers, style)
  options = {}
  options[:num_records] = num_customers
  options[:style] = style
  options[:query_params] = {}
  options[:query_params][:id_in] = customers_ids
  link, = query_link(CustomerSearch, nil, options)
  link.html_safe
end

#growth_indicator(var_value) ⇒ ActiveSupport::SafeBuffer?

Renders an up/down arrow icon colored by the sign of a variance value.

Parameters:

  • var_value (Numeric, nil)

    variance value

Returns:

  • (ActiveSupport::SafeBuffer, nil)

    the icon HTML, or nil when blank or zero



37
38
39
40
41
42
43
44
45
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 37

def growth_indicator(var_value)
  return unless var_value

  if var_value.positive?
    fa_icon('arrow-up', family: :solid, class: 'text-success')
  elsif var_value.negative?
    fa_icon('arrow-down', family: :solid, class: 'text-danger')
  end
end

#hash_to_form_params(hash) ⇒ Hash

Flattens a hash into identity-compared form params for button_to,
dropping blank values while preserving duplicate array keys.

Parameters:

  • hash (Hash)

    params to flatten

Returns:

  • (Hash)

    flattened params (identity-compared)



419
420
421
422
423
424
425
426
427
428
429
430
431
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 419

def hash_to_form_params(hash)
  cleaned_hash = hash.compact_blank
  pairs        = cleaned_hash.to_query.split(Rack::Utils::DEFAULT_SEP)
  flattened_hash_params = {} # This allows duplicate keys which is what we want for array input tags
  flattened_hash_params.compare_by_identity
  pairs.map do |pair|
    key, value = pair.split('=', 2).map { |str| Rack::Utils.unescape(str) }
    next if value.blank?

    flattened_hash_params[key] = value
  end
  flattened_hash_params
end

#inbound_outbound_blank_boolean_collection_for_select(blank_name = 'All Directions') ⇒ Array<Array(String, Boolean, String)>

Builds an inbound/outbound select collection with a leading blank option.

Parameters:

  • blank_name (String) (defaults to: 'All Directions')

    label for the blank option (defaults to 'All Directions')

Returns:

  • (Array<Array(String, Boolean, String)>)

    label/value pairs for options_for_select

See Also:



274
275
276
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 274

def inbound_outbound_blank_boolean_collection_for_select(blank_name = 'All Directions')
  inbound_outbound_boolean_collection_for_select(blank: blank_name)
end

#inbound_outbound_boolean_collection_for_select(blank: nil) ⇒ Array<Array(String, Boolean, String)>

Builds an inbound/outbound collection for a select tag, optionally with a
blank first option.

Parameters:

  • blank (String, nil) (defaults to: nil)

    label for a leading blank option, or nil to omit it

Returns:

  • (Array<Array(String, Boolean, String)>)

    label/value pairs for options_for_select



263
264
265
266
267
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 263

def inbound_outbound_boolean_collection_for_select(blank: nil)
  r = [['Inbound', true], ['Outbound', false]]
  r.insert(0, [blank, '']) if blank
  r
end

Builds a link to the invoiced-sales search for an employee and date range.

Parameters:

  • employee (Employee, nil)

    primary sales rep filter, or nil for all reps

  • company_id (Integer, Array<Integer>) (defaults to: [1])

    company filter (defaults to the primary company)

  • amount (Float, nil) (defaults to: nil)

    revenue amount; when nil the count is summed from the search

  • start_date (Date) (defaults to: Date.current.beginning_of_month)

    first gl date to include

  • end_date (Date) (defaults to: Date.current.end_of_month)

    last gl date to include

  • options (Hash) (defaults to: {})

    options forwarded to query_template_link

Options Hash (options):

  • :show_zero (Boolean)

    show the badge even when the count is zero (defaults to true)

  • :aggregate_method (Symbol)

    :sum or :count for the record count

  • :aggregate_column (Symbol, String)

    column to sum when aggregate_method is :sum

  • :num_records (Integer)

    pre-computed record count to display

  • :format (Symbol)

    :currency formats the count as currency

  • :query_params (Hash)

    search filter params for the query template

Returns:

  • (String)

    the link HTML



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 293

def invoiced_link_to(employee, company_id = [1], amount = nil,
                     start_date = Date.current.beginning_of_month,
                     end_date = Date.current.end_of_month,
                     options = {})
  options.reverse_merge!(show_zero: true)

  if amount.nil?
    options[:aggregate_method] = :sum
    options[:aggregate_column] = :revenue_consolidated
  else
    options[:num_records] = amount
  end
  options[:format] = :currency
  # options[:link_method] = :link
  options[:query_params] = {}
  options[:query_params][:company_id_in] = company_id
  options[:query_params][:gl_date_gteq] = start_date
  options[:query_params][:gl_date_lteq] = end_date
  options[:query_params][:invoice_type_in] = [Invoice::SO] # if employee
  options[:query_params][:report_grouping] = Customer::ReportGrouping.direct_sales_report_grouping
  options[:query_params][:primary_sales_rep_id_includes] = employee if employee
  query_template_link(InvoiceSearch, nil, options)[0]
end

Builds a link to the open-activities search for an employee on a date.

Parameters:

  • employee_id (Integer)

    assigned resource filter

  • oa_count (Integer)

    pre-computed open activity count to display

  • date (Date)

    the date the activities are open on

  • options (Hash) (defaults to: {})

    options forwarded to query_template_link

Options Hash (options):

  • :num_records (Integer)

    pre-computed record count to display

  • :query_params (Hash)

    search filter params for the query template

Returns:

  • (String)

    the link HTML



326
327
328
329
330
331
332
333
334
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 326

def open_activities_link_to(employee_id, oa_count, date, options = {})
  options[:num_records] = oa_count
  options[:query_params] = {}
  options[:query_params][:open_on_date] = date
  options[:query_params][:assigned_resource_id] = [employee_id]
  options[:query_params][:activity_type_id] = ['Any']
  link, = query_template_link(ActivitySearch, nil, options)
  link.html_safe
end

#opposite_growth(prev_value, cur_value) ⇒ ActiveSupport::SafeBuffer?

Renders an up/down arrow with inverted colors (up is bad/red, down is
good/green) comparing the current period value to the previous one.

Parameters:

  • prev_value (Numeric)

    previous period value

  • cur_value (Numeric, nil)

    current period value

Returns:

  • (ActiveSupport::SafeBuffer, nil)

    the indicator HTML, or nil when cur_value is blank



102
103
104
105
106
107
108
109
110
111
112
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 102

def opposite_growth(prev_value, cur_value)
  return unless cur_value

  if cur_value > prev_value
    fa_icon('arrow-up', family: :solid, style: 'color:darkred')
  elsif cur_value < prev_value
    fa_icon('arrow-down', family: :solid, style: 'color:darkgreen')
  else
    (:i, '-', style: 'color:darkyellow')
  end
end

Builds a search submit button displaying a record count.

Parameters:

  • search_klass (Class)

    search class to instantiate the query template from

  • name_key (Symbol, String, nil) (defaults to: nil)

    named query template key, or nil for a default template

  • options (Hash) (defaults to: {})

    display options, also forwarded to instantiate_query_template

Options Hash (options):

  • :style (Integer)

    size preset: 0 bold small, 1 small, 2 large

  • :num_records (Integer)

    pre-computed record count to display

  • :query_params (Hash)

    search filter params for the query template

Returns:

  • (Array(ActiveSupport::SafeBuffer, Integer))

    the button HTML and the record count



442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 442

def query_link(search_klass, name_key = nil, options = {})
  st = 'font-weight: bold; font-size: 12px;' if options[:style] == 0
  st = 'font-size: 12px;' if options[:style] == 1
  st = 'font-size: 16px;' if options[:style] == 2
  qt = search_klass.instantiate_query_template(name_key, options)
  link_names = []
  num_records = options[:num_records].to_f.round
  link_names << (:span, values_no_symbol(num_records))

  [
    button_to(
      searches_path,
      method: :post,
      params: hash_to_form_params(qt.to_params),
      class: 'btn-link btn p-0 m-0',
      style: st
    ) { link_names.compact.join.html_safe },
    num_records
  ]
end

Builds a path to the reconciliation report for a year/month scoped to a
company and ledger account.

Parameters:

  • year (Integer)

    report year

  • month (Integer)

    report month

  • company_id (Integer)

    company filter

  • account_id (Integer)

    ledger account filter

Returns:

  • (String)

    the report path



404
405
406
407
408
409
410
411
412
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 404

def reconciliation_link(year, month, company_id, )
  params = {}
  params[:command] = {}
  params[:command][:years] = year
  params[:command][:months] = month
  params[:command][:company_ids] = [company_id]
  params[:command][:ledger_account_ids] = []
  reports_reconciliation_path(params)
end

#sc_state(status) ⇒ ActiveSupport::SafeBuffer

Renders a badge with the titleized status, danger when paid out and
warning otherwise.

Parameters:

  • status (String)

    state value (e.g. 'paid_out')

Returns:

  • (ActiveSupport::SafeBuffer)

    the badge HTML



250
251
252
253
254
255
256
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 250

def sc_state(status)
  if status == 'paid_out'
    (:span, status.titleize.downcase, class: 'badge bg-danger')
  else
    (:span, status.titleize.downcase, class: 'badge bg-warning')
  end
end

#value_ptg(var_value) ⇒ ActiveSupport::SafeBuffer?

Formats a variance value as a percentage string, or a '-' when zero.

Parameters:

  • var_value (Numeric, nil)

    variance percentage value

Returns:

  • (ActiveSupport::SafeBuffer, nil)

    the formatted value HTML, or nil when blank



118
119
120
121
122
123
124
125
126
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 118

def value_ptg(var_value)
  return unless var_value

  if var_value.positive? || var_value.negative?
    (:i, '') + " #{var_value} %"
  else
    (:i, '-')
  end
end

#values_format(value, currency = "USD") ⇒ String, ...

Formats a value as a localized currency amount, or a '-' span when zero.

Parameters:

  • value (Numeric, nil)

    amount to format

  • currency (String) (defaults to: "USD")

    ISO currency code (defaults to "USD")

Returns:

  • (String, ActiveSupport::SafeBuffer, nil)

    the formatted amount, or nil when blank



133
134
135
136
137
138
139
140
141
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 133

def values_format(value, currency = "USD")
  return unless value

  if value.present? && (value.positive? || value.negative?)
    Money.from_amount(value, currency).format
  else
    (:span, '-')
  end
end

#values_format_with_not_decimals(value, currency = "USD") ⇒ String, ...

Formats a value as a currency amount without decimal places, or a '-' span
when zero.

Parameters:

  • value (Numeric, nil)

    amount to format

  • currency (String) (defaults to: "USD")

    ISO currency code (defaults to "USD")

Returns:

  • (String, ActiveSupport::SafeBuffer, nil)

    the formatted amount, or nil when blank



149
150
151
152
153
154
155
156
157
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 149

def values_format_with_not_decimals(value, currency = "USD")
  return unless value

  if value.present? && (value.positive? || value.negative?)
    Money.from_amount(value, currency).format.slice(0...-3)
  else
    (:span, '-')
  end
end

#values_format_without_symbol(value) ⇒ String, ...

Formats a value with thousands separators and no currency symbol, or a
'-' span when zero.

Parameters:

  • value (Numeric, nil)

    value to format

Returns:

  • (String, ActiveSupport::SafeBuffer, nil)

    the formatted value, or nil when blank



164
165
166
167
168
169
170
171
172
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 164

def values_format_without_symbol(value)
  return unless value

  if value.positive? || value.negative?
    value.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
  else
    (:span, '-')
  end
end

#values_no_symbol(value) ⇒ String, ...

Formats a value with thousands separators and no currency symbol, or a
'-' span when zero.

Parameters:

  • value (Numeric, nil)

    value to format

Returns:

  • (String, ActiveSupport::SafeBuffer, nil)

    the formatted value, or nil when blank

See Also:



180
181
182
183
184
185
186
187
188
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 180

def values_no_symbol(value)
  return unless value

  if value.positive? || value.negative?
    value.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
  else
    (:span, '-')
  end
end

#var_percentage(var_value) ⇒ ActiveSupport::SafeBuffer?

Renders a variance percentage with an up/down arrow colored by sign.

Parameters:

  • var_value (Numeric, nil)

    variance percentage value

Returns:

  • (ActiveSupport::SafeBuffer, nil)

    the indicator HTML, a '-' span, or nil when blank



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 15

def var_percentage(var_value)
  return (:span, '-', class: 'text-body-secondary') unless var_value

  if var_value.positive?
    (:span, class: 'text-success') do
      fa_icon('arrow-up', family: :solid, class: 'me-1') +
        (:span, "#{var_value}%")
    end
  elsif var_value.negative?
    (:span, class: 'text-danger') do
      fa_icon('arrow-down', family: :solid, class: 'me-1') +
        (:span, "#{var_value}%")
    end
  else
    (:span, '-', class: 'text-body-secondary')
  end
end

#var_percentage_opposite(var_value) ⇒ ActiveSupport::SafeBuffer?

Renders a variance percentage with inverted colors (positive is bad/red,
negative is good/green) for metrics where growth is undesirable.

Parameters:

  • var_value (Numeric, nil)

    variance percentage value

Returns:

  • (ActiveSupport::SafeBuffer, nil)

    the indicator HTML, or nil when blank



84
85
86
87
88
89
90
91
92
93
94
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 84

def var_percentage_opposite(var_value)
  return unless var_value

  if var_value.positive?
    fa_icon('arrow-up', family: :solid, style: 'color:darkred') + " #{var_value} %"
  elsif var_value.negative?
    fa_icon('arrow-down', family: :solid, style: 'color:darkgreen') + " #{var_value} %"
  else
    (:i, '-')
  end
end

#variance_color_class(value) ⇒ String

Returns a Bootstrap text color class based on the sign of a variance value.
Positive values get text-success, negative get text-danger, zero gets nothing.

Parameters:

  • value (Numeric, nil)

    variance value

Returns:

  • (String)

    'text-success', 'text-danger', or an empty string



67
68
69
70
71
72
73
74
75
76
77
# File 'app/helpers/crm/reports/gross_sales_report_helper.rb', line 67

def variance_color_class(value)
  return '' unless value

  if value.positive?
    'text-success'
  elsif value.negative?
    'text-danger'
  else
    ''
  end
end