Class: Analytic::BudgetFact
- Inherits:
-
ApplicationRecord
- Object
- ApplicationRecord
- Analytic::BudgetFact
- Includes:
- Utility
- Defined in:
- app/models/analytic/budget_fact.rb,
app/models/analytic/budget_fact/refresher.rb
Overview
== Schema Information
Table name: analytic_budget_facts
Database name: primary
id :integer not null, primary key
actual_accumulated :integer
actual_accumulated_previous :integer
actual_accumulated_previous_diff :integer
actual_accumulated_previous_percent :decimal(12, 2)
actual_month :integer
actual_month_previous :integer
actual_month_previous_diff :integer
actual_month_previous_percent :decimal(12, 2)
budget_accumulated :integer
budget_accumulated_diff :integer
budget_accumulated_percent :decimal(12, 2)
budget_month :integer
budget_month_diff :integer
budget_month_percent :decimal(12, 2)
is_revenue :boolean
month :integer
year :integer
created_at :datetime not null
updated_at :datetime not null
budget_dimension_id :integer
Indexes
idx_budget_facts_year_month_dimension_unique (year,month,budget_dimension_id) UNIQUE
Defined Under Namespace
Classes: Refresher
Belongs to collapse
-
#budget_dimension ⇒ Analytic::BudgetDimension?
The company / ledger-account / business-unit / project / supplier slice this fact row aggregates.
Class Method Summary collapse
-
.build_percentage(diff, original) ⇒ Numeric
Build a signed percentage change for a diff against an original amount.
-
.refresh_data_for_month(year = Date.current.year, month, incremental: false, &progress_block) ⇒ Boolean
Refresh budget facts for a given year/month.
Instance Method Summary collapse
-
#is_zero? ⇒ Boolean
True when every monetary measure on this fact row is zero.
Class Method Details
.build_percentage(diff, original) ⇒ Numeric
Build a signed percentage change for a diff against an original amount.
68 69 70 71 72 73 74 |
# File 'app/models/analytic/budget_fact.rb', line 68 def self.build_percentage(diff, original) if diff.zero? 0 else (original.zero? ? 100 : ((diff.to_f / original) * 100)) end end |
.refresh_data_for_month(year = Date.current.year, month, incremental: false, &progress_block) ⇒ Boolean
Refresh budget facts for a given year/month.
The heavy lifting — building the in-memory ledger/budget indexes and writing
the fact rows — lives in Refresher, a fresh instance
per call. That keeps every run's indexes on its own object, so concurrent
refreshes (the :budgets Sidekiq queue runs at concurrency 16, and
BudgetRefresherAllWorker fans out 12 monthly jobs) can't read or overwrite
each other's data. Previously these were class instance variables guarded
only by a process-local mutex, which serialized refreshes without curing the
cross-report data bleed. See
doc/tasks/202606252210_MEMOIZATION_THREAD_SAFETY_AUDIT.md §3e.
59 60 61 |
# File 'app/models/analytic/budget_fact.rb', line 59 def self.refresh_data_for_month(year = Date.current.year, month, incremental: false, &progress_block) Refresher.new(year, month, incremental: incremental, progress_block: progress_block).run end |
Instance Method Details
#budget_dimension ⇒ Analytic::BudgetDimension?
Returns the company / ledger-account /
business-unit / project / supplier slice this fact row aggregates.
40 |
# File 'app/models/analytic/budget_fact.rb', line 40 belongs_to :budget_dimension, optional: true |
#is_zero? ⇒ Boolean
Returns true when every monetary measure on this fact row is zero.
77 78 79 |
# File 'app/models/analytic/budget_fact.rb', line 77 def is_zero? [budget_month, actual_month, budget_accumulated, actual_accumulated, actual_month_previous, actual_accumulated_previous].all?(&:zero?) end |