Class: Crm::Reports::BudgetController
- Inherits:
-
ReportsController
- Object
- ReportsController
- Crm::Reports::BudgetController
- Defined in:
- app/controllers/crm/reports/budget_controller.rb
Constant Summary collapse
- MONETARY_FACT_FIELDS =
Fact fields that represent monetary amounts (integers) and must be
multiplied by the exchange rate when converting currencies.
Percentage fields are ratios and stay unchanged. %i[ budget_month actual_month budget_month_diff budget_accumulated actual_accumulated budget_accumulated_diff actual_month_previous actual_month_previous_diff actual_accumulated_previous actual_accumulated_previous_diff ].freeze
- PERCENTAGE_FORMULAS =
Formulas for recalculating percentage fields after merging facts.
{ percentage_field => [diff_field, base_field] } { budget_month_percent: %i[budget_month_diff budget_month], budget_accumulated_percent: %i[budget_accumulated_diff budget_accumulated], actual_month_previous_percent: %i[actual_month_previous_diff actual_month], actual_accumulated_previous_percent: %i[actual_accumulated_previous_diff actual_accumulated] }.freeze
Class Method Summary collapse
-
.company_currencies ⇒ Object
Maps company ID (string) → native currency code, built from the database.
-
.consolidated_currency ⇒ Object
The consolidated (reporting) currency used when viewing multiple companies.
Instance Method Summary collapse
-
#children ⇒ Object
Turbo Frame endpoint: returns child dimension rows on-demand when the user expands a drill-down row.
- #show ⇒ Object
Class Method Details
.company_currencies ⇒ Object
Maps company ID (string) → native currency code, built from the database.
e.g. { "1" => "USD", "2" => "CAD", "4" => "EUR" }
23 24 25 26 |
# File 'app/controllers/crm/reports/budget_controller.rb', line 23 def self.company_currencies @company_currencies ||= Company.sales_companies.pluck(:id, :currency) .to_h { |id, cur| [id.to_s, cur] } end |
.consolidated_currency ⇒ Object
The consolidated (reporting) currency used when viewing multiple companies.
Reads from Company#consolidated_currency, falls back to the global constant.
30 31 32 |
# File 'app/controllers/crm/reports/budget_controller.rb', line 30 def self.consolidated_currency @consolidated_currency ||= Company.sales_companies.pick(:consolidated_currency).presence || CONSOLIDATED_CURRENCY end |
Instance Method Details
#children ⇒ Object
Turbo Frame endpoint: returns child dimension rows on-demand when the
user expands a drill-down row. Avoids pre-rendering ~6,500 hidden
supplier-level rows in the initial HTML.
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/controllers/crm/reports/budget_controller.rb', line 63 def children (:report, Budget) set_filter_params dimension_id = params[:dimension_id].to_i level = (params[:level] || 1).to_i parent_row_id = params[:parent_row_id] # Load budget facts for the current period @budget_facts = Analytic::BudgetFact .where(month: @month, year: @year) .index_by(&:budget_dimension_id) if @merge_companies merge_company_facts! elsif @convert_currency apply_currency_conversion! end # Load children of this dimension (select only needed columns) children = Analytic::BudgetDimension .where(company_id: @data_company_id, parent_id: dimension_id) .select(:id, :description, :parent_id, :budget_group_id, :supplier_id) .order(:description) .to_a # Check grandchildren existence for expand buttons (single query) child_ids = children.map(&:id) @dimension_children_by_parent = if child_ids.any? Analytic::BudgetDimension .where(company_id: @data_company_id, parent_id: child_ids) .select(:id, :description, :parent_id, :budget_group_id, :supplier_id) .order(:description) .group_by(&:parent_id) else {} end render partial: "budget_children_rows", locals: { children: children, level: level, parent_row_id: parent_row_id } end |
#show ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'app/controllers/crm/reports/budget_controller.rb', line 34 def show (:report, Budget) set_filter_params # Build cache key BEFORE loading heavy data. # On cache hit the view skips re-rendering the table, but we still need # the data for filter dropdowns and the "Last generated" badge. @budget_table_cache_key = budget_table_cache_key # Always load lightweight "last generated" timestamp for the badge @last_generated_at = Analytic::BudgetFact .where(month: @month, year: @year) .maximum(:created_at) # Only load heavy report data when the fragment cache is cold. # On cache hit this skips ~40k AR object instantiations + hash building. unless fragment_exist?(@budget_table_cache_key) load_budget_data if @merge_companies merge_company_facts! elsif @convert_currency apply_currency_conversion! end end end |