Class: BudgetsController
- Inherits:
-
CrmController
- Object
- ActionController::Base
- ApplicationController
- CrmController
- BudgetsController
- Defined in:
- app/controllers/budgets_controller.rb
Overview
== Schema Information
Table name: budgets
id :integer not null, primary key
description :string
company_id :integer
ledger_account_id :integer
business_unit_id :integer
supplier_id :integer
ledger_project_id :integer
year :integer
quarter :integer
month :integer
currency :string
amount :decimal(12, 2)
consolidated_amount :decimal(12, 2)
exchange_rate :decimal(, )
is_revenue :boolean
all_ledger_company_account_ids_1 :text default([]), is an Array
all_ledger_company_account_ids_2 :text default([]), is an Array
creator_id :integer
updater_id :integer
created_at :datetime not null
updated_at :datetime not null
Constant Summary
Constants included from Controllers::ReferenceFindable
Controllers::ReferenceFindable::ID_EMBEDDED_PATTERNS
Constants included from Controllers::AnalyticsEvents
Controllers::AnalyticsEvents::MAX_QUEUED_EVENTS, Controllers::AnalyticsEvents::SESSION_KEY
Constants included from Controllers::ErrorRendering
Controllers::ErrorRendering::NON_CONTENT_PATH_PREFIXES
Constants included from Www::SeoHelper
Www::SeoHelper::AWARDS, Www::SeoHelper::CA_ADDRESS, Www::SeoHelper::CA_BUSINESS_HOURS, Www::SeoHelper::CA_CONTACT_POINT, Www::SeoHelper::CA_CURRENCIES, Www::SeoHelper::CA_DESCRIPTION, Www::SeoHelper::CA_FOUNDING_DATE, Www::SeoHelper::CA_GLOBAL_LOCATION_NUMBER, Www::SeoHelper::CA_LEGAL_NAME, Www::SeoHelper::CA_LOCAL_BUSINESS, Www::SeoHelper::CA_ONLINE_STORE, Www::SeoHelper::CA_RETURN_POLICY, Www::SeoHelper::CA_SALES_DEPARTMENT, Www::SeoHelper::CA_SERVICE_AREA, Www::SeoHelper::CA_URL, Www::SeoHelper::CA_VAT_ID, Www::SeoHelper::CA_WAREHOUSE_DEPARTMENT, Www::SeoHelper::CA_WAREHOUSE_HOURS, Www::SeoHelper::COMPANY_EMAIL, Www::SeoHelper::COMPANY_LOGO, Www::SeoHelper::COMPANY_NAME, Www::SeoHelper::COMPANY_SLOGAN, Www::SeoHelper::EXPERTISE, Www::SeoHelper::FAX_NUMBER, Www::SeoHelper::GS1_COMPANY_PREFIX, Www::SeoHelper::ISO6523_CODE, Www::SeoHelper::PAYMENT_METHODS, Www::SeoHelper::PHONE_NUMBER, Www::SeoHelper::PRIMARY_NAICS, Www::SeoHelper::REFUND_TYPE, Www::SeoHelper::RETURN_FEES, Www::SeoHelper::RETURN_METHOD, Www::SeoHelper::RETURN_POLICY_CATEGORY, Www::SeoHelper::SECONDARY_NAICS, Www::SeoHelper::SOCIAL_PROFILES, Www::SeoHelper::US_ADDRESS, Www::SeoHelper::US_BUSINESS_HOURS, Www::SeoHelper::US_CONTACT_POINT, Www::SeoHelper::US_CURRENCIES, Www::SeoHelper::US_DESCRIPTION, Www::SeoHelper::US_FOUNDING_DATE, Www::SeoHelper::US_GLOBAL_LOCATION_NUMBER, Www::SeoHelper::US_IMAGE, Www::SeoHelper::US_LEGAL_NAME, Www::SeoHelper::US_LOCAL_BUSINESS, Www::SeoHelper::US_ONLINE_STORE, Www::SeoHelper::US_RETURN_POLICY, Www::SeoHelper::US_SALES_DEPARTMENT, Www::SeoHelper::US_SERVICE_AREA, Www::SeoHelper::US_TAX_ID, Www::SeoHelper::US_URL, Www::SeoHelper::US_WAREHOUSE_DEPARTMENT, Www::SeoHelper::US_WAREHOUSE_HOURS
Constants included from IconHelper
IconHelper::CUSTOM_ICON_MAP, IconHelper::CUSTOM_SVG_DIR, IconHelper::DEFAULT_FAMILY
Instance Method Summary collapse
-
#create ⇒ Object
POST /budgets — persist a single budget row.
-
#destroy ⇒ Object
DELETE /budgets/:id — destroy the budget row.
-
#do_import ⇒ Object
POST /budgets/do_import — parse the uploaded CSV via Budget.summary_import_from_csv and bounce to the budget report (refresh runs synchronously inside the import, so by the time the user lands the numbers are fresh).
-
#download_sample_csv ⇒ Object
GET /budgets/download_sample_csv — serve the canonical bulk-import template so users start from the right column layout.
-
#edit ⇒ Object
GET /budgets/:id/edit — render the edit form.
-
#import ⇒ Object
GET /budgets/import — render the bulk-import form.
-
#index ⇒ Object
GET /budgets — there's no flat list; redirect into the budget-vs-actual report which is the canonical entry point.
-
#new ⇒ Object
GET /budgets/new — render the new-budget form.
-
#refresh_report ⇒ Object
POST /budgets/refresh_report — recompute the budget-vs-actual snapshot.
-
#show ⇒ Object
GET /budgets/:id — show a single Budget row (one company / ledger-account / period / supplier-or-project combination).
-
#show_budgets_for_fact ⇒ Object
GET /budgets/show_budgets_for_fact — drill-down counterpart to #show_ledger_entries_for_fact: takes the same fact cell and opens the budget rows that summed to it (so the user can edit the budgeted figure directly).
-
#show_ledger_entries_for_fact ⇒ Object
GET /budgets/show_ledger_entries_for_fact — drill-down from a
BudgetFactcell on the report into the underlying GL entries that built it. -
#update ⇒ Object
PATCH/PUT /budgets/:id — update a budget row.
Methods inherited from CrmController
#access_denied, #context_id, #context_object, #crm_home_path, #current_ability, #default_url_options, #download_temp, #get_tempfile_path_for_download, #init_status_job_collector, #initialize_crm_lazy_chunks, #persist_enqueued_status_jobs, #record_not_found, #redirect_to_job_or_fallback, #render_edit_action, #set_context, #set_download_path, #stash_file_for_temp_download, #sync_admin_presence_cookie
Methods inherited from ApplicationController
#account_impersonated?, #add_to_flash, #after_sign_in_path_for, #bypass_forgery_protection?, #chat_enabled?, #cloudflare_cleared?, #default_catalog, #default_url_options, #enable_turbo_frames, #find_publication, #fix_invalid_accept_header, #init_js_utils, #is_globals_call?, #layout_by_resource, #locale_store, #redirect_to, #require_employee_for_crm, #set_base_host, #set_real_ip, #set_report_errors_for, #should_render_layout?, #stamp_impersonation_context, #warmlyyours_canada_ip?, #warmlyyours_ip?, #y
Methods included from Controllers::ReturnPathHandling
#check_for_return_path, #redirect_to_return_path_or_default
Methods included from Controllers::AnalyticsEvents
#consume_queued_analytics_events, #track_event
Methods included from Controllers::DeviceDetection
Methods included from Controllers::SubdomainDetection
#is_crm_request?, #is_www_request?, #json_request?
Methods included from Controllers::TurboSafeRedirect
Methods included from Controllers::TrackingDetection
#bot_request?, #gdpr_country?, #gdpr_country_data, #prevent_bots, #set_tracking_cookie, #track_visitor?
Methods included from Controllers::AcceleratedFileSending
#send_file_accelerated, #send_upload_accelerated
Methods included from Controllers::ErrorRendering
#excp_string, #mail_to_for_error_reporting, #render_400, #render_404, #render_406, #render_410, #render_500, #render_invalid_authenticity_token, #render_ip_spoof_error, #render_unpermitted_parameters, #safe_referer_or_fallback
Methods included from Controllers::TurnstileVerification
#load_turnstile_script_tag, #turnstile_lazy_widget, #turnstile_script_tag, #turnstile_widget, #validate_turnstile!
Methods included from Controllers::CloudflareCaching
edge_cached, #edge_cached_action?, #reset_cloudflare_cache, #set_cloudflare_cache, #skip_edge_cache!, #skip_session
Methods included from Controllers::Webpackable
#preload_webpack_fonts, #webpack_css_include, #webpack_css_url, #webpack_js_include, #wpd_is_running?
Methods included from Controllers::Localizable
#cloudflare_country_locale, #determine_request_locale, #geocoder_locale, #guest_user_locale_check, #locale_optional_www_auth_path?, #param_locale, #set_locale, #set_request_locale, #skip_localization?, #warmlyyours_ip_locale
Methods included from Controllers::Authenticable
#access_denied, #authenticate_account, #authenticate_account!, #authenticate_account_from_login_token!, #check_is_a_manager, #check_is_a_sales_manager, #check_is_an_admin, #check_is_an_employee, #check_party, #clear_mismatched_guest_user, #create_guest_user, #credentials?, #current_or_guest_user, #current_or_guest_user_id_read_only, #current_user, #devise_mapping, #fully_logged_in?, #generate_bot_id, #guest_user, #identifiable?, #init_current_user, #initialize_guest, #load_context_user, #logging_in, #resource, #resource_name, #restrict_access_for_non_employees, #scrubbed_request_path, #user_object, #warn_on_session_guest_id_leak
Methods included from ApplicationHelper
#better_number_to_currency, #check_force_logout, #check_or_cross, #check_or_times, #embedded_tab_frame_id, #error_messages, #general_disclaimer_on_product_installation_and_local_codes, #gridjs_from_html_table, #gridjs_table, #is_wy_ip, #line_break, #parent_layout, #pass_or_fail, #render_error_messages_list, #render_video_card, #resolved_auth_form_turbo_frame, #return_path_or, #safe_css_color, #set_return_path_if_present, #set_section_if_present, #tab_frame_id, #to_underscore, #track_page?, #turbo_section_wrapper, #turbo_tabs_request?, #url_on_same_domain_as_request, #widget_index_daily_focus_index_path, #working_hours?, #yes_or_no, #yes_or_no_highlighted, #yes_or_no_with_check_or_cross, #youtube_video
Methods included from UppyUploaderHelper
#file_uploader, #image_uploader, #large_file_uploader_s3, #lead_sketch_uploader, #rma_image_uploader, #rma_image_uploader_s3, #uppy_uploader, #video_uploader
Methods included from Www::ImagesHelper
#image_asset_tag, #image_asset_url
Methods included from Www::SeoHelper
#add_page_schema, #add_webpage_schema, #canada?, #company_social_links, #ensure_context_json, #json_ld_script_tag, #local_business_schema, #online_store_id, #online_store_schema, #page_main_entity, #page_main_entity_json, #render_auto_collection_page_schema, #render_collection_page_schema, #render_local_business_schema, #render_online_store_schema, #render_page_schemas, #render_page_video_schemas, #render_webpage_schema, #render_webpage_schema_with_collections, #usa?
Methods included from UrlsHelper
#catalog_breadcrumb_links, #catalog_link, #catalog_link_for_product_line, #catalog_link_for_sku, #cms_link, #delocalized_path, #path_to_sales_product_sku, #path_to_sales_product_sku_for_product_line, #path_to_sales_product_sku_for_product_line_slug, #product_line_from_catalog_link, #protocol_neutral_url, #sanitize_external_url, #valid_external_url?
Methods included from IconHelper
#account_nav_icon, #fa_icon, #star_rating_html
Instance Method Details
#create ⇒ Object
POST /budgets — persist a single budget row.
56 57 58 59 60 61 62 63 64 |
# File 'app/controllers/budgets_controller.rb', line 56 def create @budget = Budget.new(params[:budget]) if @budget.save redirect_to(@budget, info: 'Budget was successfully created.') else render :new, status: :unprocessable_content end end |
#destroy ⇒ Object
DELETE /budgets/:id — destroy the budget row.
83 84 85 86 87 88 |
# File 'app/controllers/budgets_controller.rb', line 83 def destroy @budget = Budget.find(params[:id]) @budget.destroy redirect_to_return_path_or_default(budgets_url) end |
#do_import ⇒ Object
POST /budgets/do_import — parse the uploaded CSV via
Budget.summary_import_from_csv and bounce to the budget
report (refresh runs synchronously inside the import, so by the
time the user lands the numbers are fresh).
183 184 185 186 187 188 189 190 191 192 193 |
# File 'app/controllers/budgets_controller.rb', line 183 def do_import upload_params = params[:upload] if upload_params.nil? # upload_params[:budget_csv].blank? flash.now[:error] = 'No file was uploaded' render :import, status: :unprocessable_content else Budget.summary_import_from_csv(upload_params[:budget_csv].path) flash[:info] = 'Budget imported, report is being refreshed' redirect_to '/reports/budget' end end |
#download_sample_csv ⇒ Object
GET /budgets/download_sample_csv — serve the canonical
bulk-import template so users start from the right column layout.
197 198 199 200 |
# File 'app/controllers/budgets_controller.rb', line 197 def download_sample_csv file_path = Rails.root.join('data/import_templates/accounting/budget_sample.csv') send_file_accelerated(file_path, download: true, preserve_source: true) end |
#edit ⇒ Object
GET /budgets/:id/edit — render the edit form.
51 52 53 |
# File 'app/controllers/budgets_controller.rb', line 51 def edit @budget = Budget.find(params[:id]) end |
#import ⇒ Object
GET /budgets/import — render the bulk-import form.
177 |
# File 'app/controllers/budgets_controller.rb', line 177 def import; end |
#index ⇒ Object
GET /budgets — there's no flat list; redirect into the
budget-vs-actual report which is the canonical entry point.
35 36 37 |
# File 'app/controllers/budgets_controller.rb', line 35 def index redirect_to '/reports/budget' end |
#new ⇒ Object
GET /budgets/new — render the new-budget form.
46 47 48 |
# File 'app/controllers/budgets_controller.rb', line 46 def new @budget = Budget.new end |
#refresh_report ⇒ Object
POST /budgets/refresh_report — recompute the budget-vs-actual
snapshot. With explicit year/month we run an incremental
upsert (or full delete-reinsert when ?full=true); without
them we kick off a full-year refresh in the background.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'app/controllers/budgets_controller.rb', line 94 def refresh_report if params[:year] && params[:month] = { current_user_id: @context_user.id, year: params[:year], month: params[:month] } # Use incremental refresh (upserts) by default for faster performance # Full refresh (delete-reinsert) can be forced with ?full=true job_id = if params[:full].present? BudgetRefresherWorkerWithStatus.perform_async() else BudgetRefresherIncrementalWorker.perform_async() end redirect_to job_path(job_id) else BudgetRefresherAllWorker.perform_async flash[:info] = 'All budget reports from current year sent to background processor to be refreshed.' redirect_to root_path end end |
#show ⇒ Object
GET /budgets/:id — show a single Budget row (one company /
ledger-account / period / supplier-or-project combination).
41 42 43 |
# File 'app/controllers/budgets_controller.rb', line 41 def show @budget = Budget.find(params[:id]) end |
#show_budgets_for_fact ⇒ Object
GET /budgets/show_budgets_for_fact — drill-down counterpart to
#show_ledger_entries_for_fact: takes the same fact cell and
opens the budget rows that summed to it (so the user can edit
the budgeted figure directly). accumulated=true shows every
month in the YTD window rather than just the fact's month.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'app/controllers/budgets_controller.rb', line 159 def show_budgets_for_fact fact = Analytic::BudgetFact.find(params[:fact_id]) dimension = fact.budget_dimension query_params = {} query_params[:company_id_in] = dimension.company_id == 'all' ? [1, 2] : dimension.company_id query_params[:ledger_account_id_in] = dimension.ledger_account_ids query_params[:business_unit_id_in] = dimension.business_unit_id unless dimension.business_unit_id.nil? query_params[:ledger_project_id_in] = dimension.ledger_project_id unless dimension.ledger_project_id.nil? || (dimension.ledger_project_id == 0) query_params[:supplier_id_eq] = dimension.supplier_id unless dimension.supplier_id.nil? || (dimension.supplier_id == 0) query_params[:year_in] = fact.year query_params[:month_in] = params[:accumulated] == true ? (1..fact.month).to_a : fact.month qt = BudgetSearch.instantiate_query_template(nil, { title: 'link', auto_count: false, aggregate_method: :none, query_params: query_params }) redirect_to execute_search_path(qt.to_params) end |
#show_ledger_entries_for_fact ⇒ Object
GET /budgets/show_ledger_entries_for_fact — drill-down from a
BudgetFact cell on the report into the underlying GL entries
that built it. Translates the budget dimension (company,
account, business-unit, project, supplier) into the matching
LedgerEntrySearch params and redirects there. The period
param picks the comparison window (current vs previous year,
month vs accumulated YTD).
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'app/controllers/budgets_controller.rb', line 120 def show_ledger_entries_for_fact fact = Analytic::BudgetFact.find(params[:fact_id]) dimension = fact.budget_dimension query_params = {} query_params[:lt_company_id_in] = dimension.company_id == 'all' ? [1, 2] : dimension.company_id query_params[:ledger_company_account_id_in] = dimension.ledger_company_account_ids query_params[:business_unit_id_in] = dimension.business_unit_id unless dimension.business_unit_id.nil? query_params[:ledger_detail_project_id_in] = dimension.ledger_project_id unless dimension.ledger_project_id.nil? || (dimension.ledger_project_id == 0) query_params[:supplier_id_eq] = dimension.supplier_id unless dimension.supplier_id.nil? || (dimension.supplier_id == 0) query_params[:lt_transaction_date_gteq] = case params[:period] when 'current-month' Date.new(fact.year, fact.month).beginning_of_month.to_fs(:db) when 'current-accumulated' Date.new(fact.year, fact.month).beginning_of_year.to_fs(:db) when 'previous-month' Date.new(fact.year, fact.month).last_year.beginning_of_month.to_fs(:db) when 'previous-accumulated' Date.new(fact.year, fact.month).last_year.beginning_of_year.to_fs(:db) end query_params[:lt_transaction_date_lteq] = case params[:period] when 'current-month' Date.new(fact.year, fact.month).end_of_month.to_fs(:db) when 'current-accumulated' Date.new(fact.year, fact.month).end_of_month.to_fs(:db) when 'previous-month' Date.new(fact.year, fact.month).last_year.end_of_month.to_fs(:db) when 'previous-accumulated' Date.new(fact.year, fact.month).last_year.end_of_month.to_fs(:db) end qt = LedgerEntrySearch.instantiate_query_template(nil, { title: 'link', auto_count: false, aggregate_method: :none, query_params: query_params }) redirect_to execute_search_path(qt.to_params) end |
#update ⇒ Object
PATCH/PUT /budgets/:id — update a budget row. Responds to JSON
for the inline-edit grid on the budget report.
68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'app/controllers/budgets_controller.rb', line 68 def update @budget = Budget.find(params[:id]) respond_to do |format| if @budget.update(params[:budget]) format.html { redirect_to_return_path_or_default(budget_path(@budget)) } format.json { render json: @budget } else format.html { render :edit, status: :unprocessable_content } format.json { render json: @budget } end end end |