Class: Crm::ItemDemandForecastAdditionsController

Inherits:
CrmController show all
Defined in:
app/controllers/crm/item_demand_forecast_additions_controller.rb

Overview

Controller: item demand forecast additions.

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

Instance Method Summary collapse

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, #touch_employee_last_seen

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?, #skip_layout_for_turbo_frame?, #stamp_impersonation_context, #tab_frame_breakout_request?, #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, #registration_lead_type, #track_event

Methods included from Controllers::DeviceDetection

#device_detector, #is_ie?

Methods included from Controllers::SubdomainDetection

#is_crm_request?, #is_www_request?, #json_request?

Methods included from Controllers::TurboSafeRedirect

#redirect_to

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 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?

Instance Method Details

#createObject

Creates an item demand forecast addition.



94
95
96
97
98
99
100
101
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 94

def create
  @item_demand_forecast_addition = ItemDemandForecastAddition.new(params[:item_demand_forecast_addition])
  if @item_demand_forecast_addition.save
    redirect_to item_demand_forecast_additions_path
  else
    render :new, status: :unprocessable_content
  end
end

#create_quote_orderObject

Adds every line item of a quote or order as forecast additions on a given date.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 15

def create_quote_order
  @type = params[:type]
  @quote_order_ref = params[:quote_order_ref]
  @date = params[:date]
  if params[:quote_order_ref].blank? || params[:date].blank?
    flash.now[:error] = 'Quote/Order reference number and Date must be specified'
    render :new_quote_order, status: :unprocessable_content
  elsif params[:type] == 'order'
    order = Order.where(reference_number: params[:quote_order_ref].upcase).first
    if order.nil?
      flash.now[:error] = "Unable to find order with reference #{params[:quote_order_ref]}"
      render :new_quote_order, status: :unprocessable_content
    else
      ItemDemandForecastAddition.add_order(order, params[:date])
      flash[:info] = 'All items from Order added'
      redirect_to item_demand_forecast_additions_path
    end
  elsif params[:type] == 'quote'
    quote = Quote.where(reference_number: params[:quote_order_ref].upcase.gsub('-R', '-r')).first
    if quote.nil?
      flash.now[:error] = "Unable to find quote with reference #{params[:quote_order_ref]}"
      render :new_quote_order, status: :unprocessable_content
    else
      ItemDemandForecastAddition.add_quote(quote, params[:date])
      flash[:info] = 'All items from Quote added'
      redirect_to item_demand_forecast_additions_path
    end
  end
end

#delete_orderObject

Destroys every forecast addition tied to the same order as the given one.



183
184
185
186
187
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 183

def delete_order
  @item_demand_forecast_addition = ItemDemandForecastAddition.find(params[:id])
  ItemDemandForecastAddition.destroy_by(order_id: @item_demand_forecast_addition.order_id)
  redirect_to item_demand_forecast_additions_path(notice: 'All Item Demand Forecast Additions for order deleted')
end

#delete_quote_orderObject

Destroys every forecast addition tied to the same order or quote as the
given one.



172
173
174
175
176
177
178
179
180
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 172

def delete_quote_order
  @item_demand_forecast_addition = ItemDemandForecastAddition.find(params[:id])
  if @item_demand_forecast_addition.category == 'order'
    @item_demand_forecast_addition = ItemDemandForecastAddition.destroy_by(order_id: @item_demand_forecast_addition.order_id)
  elsif @item_demand_forecast_addition.category == 'quote'
    @item_demand_forecast_addition = ItemDemandForecastAddition.destroy_by(quote_id: @item_demand_forecast_addition.quote_id)
  end
  redirect_to item_demand_forecast_additions_path(notice: 'All Item Demand Forecast Additions for #{@item_demand_forecast_addition.category} deleted')
end

#destroyObject

Destroys the item demand forecast addition.



160
161
162
163
164
165
166
167
168
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 160

def destroy
  @item_demand_forecast_addition = ItemDemandForecastAddition.find(params[:id])
  if @item_demand_forecast_addition.destroy
    redirect_to item_demand_forecast_additions_path(notice: 'Item Demand Forecast Addition deleted')
  else
    redirect_to item_demand_forecast_additions_path,
                flash: { error: @item_demand_forecast_addition.errors_to_s.presence || 'Could not delete forecast addition.' }
  end
end

#do_import_from_csvObject

Bulk-imports forecast additions from an uploaded CSV, skipping rows with
an invalid date (AppSignal #4819) and surfacing all row-level errors.



116
117
118
119
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
153
154
155
156
157
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 116

def do_import_from_csv
  forecasts = []
  errors = []
  imported_forecasts_csv = params.dig(:upload, :imported_forecasts_csv)
  file_path = imported_forecasts_csv.tempfile.path.to_s
  CSV.foreach(file_path, headers: true) do |row|
    if row.first[1].present?
      sku = row.first[1].to_s.squish.upcase
      item = Item.where('sku ilike ?', sku).first
      errors << "Item #{sku} not found." if item.nil?

      parsed_date = parse_forecast_date(row['Date'])
      if parsed_date.nil?
        # Skip the row so one malformed date doesn't 500 the whole import
        # (AppSignal #4819). Surface the problem alongside the other
        # row-level errors the view already renders.
        errors << "Invalid date '#{row['Date']}' for SKU #{sku}."
        next
      end

      idf = ItemDemandForecastAddition.new(
        item_id: item&.id,
        quantity: row['Quantity'].to_i,
        date: parsed_date,
        category: row['Category'],
        description: row['Description'],
        store_id: row['Store']
      )
      errors += idf.errors.full_messages unless idf.valid?
      forecasts << idf
    end
  end

  if errors.any?
    flash.now[:error] = errors.uniq.join(', ')
    render :import_from_csv, status: :unprocessable_content
  else
    forecasts.each(&:save!)
    flash[:info] = 'Forecast additions imported'
    redirect_to item_demand_forecast_additions_path
  end
end

#do_mass_date_updateObject

Applies the submitted new date to the selected forecast additions
(and their children, matched by parent_id).



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 52

def do_mass_date_update
  @item_demand_forecast_additions = ItemDemandForecastAddition.where(id: Array(params[:additions_ids]).map(&:to_i).reject(&:zero?))
                                                              .or(ItemDemandForecastAddition.where(parent_id: Array(params[:additions_ids]).map(&:to_i).reject(&:zero?)))
  begin
    if @item_demand_forecast_additions.update_all(date: params[:new_date])
      flash[:info] = 'Item Demand Forecast Additions updated'
      redirect_to item_demand_forecast_additions_path
    else
      flash[:error] = 'There was an error updating the Item Demand Forecast Additions.'
      redirect_to item_demand_forecast_additions_path
    end
  rescue StandardError => e
    flash[:error] = "An error occurred: #{e.message}"
    redirect_to item_demand_forecast_additions_path
  end
end

#download_sample_csvObject

Downloads the sample CSV import template.



190
191
192
193
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 190

def download_sample_csv
  file_path = Rails.root.join('data/import_templates/item_demand_forecast/item_demand_forecast_additions_sample.csv')
  send_file_accelerated(file_path, download: true, preserve_source: true)
end

#editObject

Renders the form to edit an item demand forecast addition.



89
90
91
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 89

def edit
  @item_demand_forecast_addition = ItemDemandForecastAddition.find(params[:id])
end

#indexObject

Lists this week's and future item demand forecast additions.



5
6
7
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 5

def index
  @item_demand_forecast_additions = ItemDemandForecastAddition.where(date: Date.current.monday..).order(:date, :id)
end

#mass_date_updateObject

Renders the form to set a new date for the selected forecast additions.



46
47
48
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 46

def mass_date_update
  @additions_ids = Array(params[:additions_ids]).map(&:to_i).reject(&:zero?)
end

#mass_deleteObject

Destroys the selected forecast additions (and their children, matched by
parent_id).



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 71

def mass_delete
  @item_demand_forecast_additions = ItemDemandForecastAddition.where(id: Array(params[:additions_ids]).map(&:to_i).reject(&:zero?))
                                                              .or(ItemDemandForecastAddition.where(parent_id: Array(params[:additions_ids]).map(&:to_i).reject(&:zero?)))
  begin
    if @item_demand_forecast_additions.destroy_all
      flash[:info] = 'Item Demand Forecast Additions deleted'
      redirect_to item_demand_forecast_additions_path
    else
      flash[:error] = 'There was an error deleting the Item Demand Forecast Additions.'
      redirect_to item_demand_forecast_additions_path
    end
  rescue StandardError => e
    flash[:error] = "An error occurred: #{e.message}"
    redirect_to item_demand_forecast_additions_path
  end
end

#newObject

Renders the form for a new item demand forecast addition.



10
11
12
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 10

def new
  @item_demand_forecast_addition = ItemDemandForecastAddition.new
end

#updateObject

Updates an item demand forecast addition.



104
105
106
107
108
109
110
111
112
# File 'app/controllers/crm/item_demand_forecast_additions_controller.rb', line 104

def update
  @item_demand_forecast_addition = ItemDemandForecastAddition.find(params[:id])
  if @item_demand_forecast_addition.update(params[:item_demand_forecast_addition])
    flash[:info] = 'Item Demand Forecast Addition updated'
    redirect_to item_demand_forecast_additions_path
  else
    render :edit, status: :unprocessable_content
  end
end