Class: CrmController

Inherits:
ApplicationController show all
Includes:
Controllers::ReferenceFindable, Controllers::TabAccessDeniable
Defined in:
app/controllers/crm_controller.rb

Overview

Controller: crm.

Direct Known Subclasses

AccountingDashboardController, ActivitiesController, ActivityTypesController, AddressesController, Admin::AdminController, Admin::AiUsageLogsController, Admin::BackgroundMigrationsController, Admin::CampaignIntegrationsController, Admin::CspReportsController, Admin::EmbeddingsController, Admin::GmailSignaturesController, Admin::InboundEmailsController, Admin::OauthCredentialsController, Admin::Privacy::DeletionRequestsController, ArticleFaqsController, ArticleProceduresController, ArticleTechnicalsController, ArticleTrainingsController, ArticlesController, AssignmentQueuesController, AudiencesController, BankAccountsController, BanksController, BudgetGroupsController, BudgetRulesController, BudgetsController, BuyingGroupsController, CalendarsController, CallLogsController, CallRecordsController, CampaignDeliveriesController, CampaignEmailsController, CampaignsController, CatalogItemsController, CatalogsController, ChecksController, CommunicationsController, ContactPointsController, ContactsController, CouponsController, CreditCardVaultsController, CreditMemosController, Crm::AccountsController, Crm::AccountsPayableDashboardController, Crm::ActivityAgendasController, Crm::AdActionItemsController, Crm::AdditionalCallCreditsController, Crm::AdsOverviewController, Crm::AgreementsController, Crm::Amazon::DatadiveImportsController, Crm::Amazon::ListingsController, Crm::Amazon::SchemasController, Crm::AmazonAPlusContentsController, Crm::AmazonAdsOauthController, Crm::AmazonBrowseNodesController, Crm::AmazonDashboardController, Crm::AmazonImagesController, Crm::AmazonNotificationsController, Crm::AmazonProductsController, Crm::AmazonTransparencyCodesController, Crm::ApiTokensController, Crm::ArticleRevisionRelatedMaterialsController, Crm::ArticleRevisionsController, Crm::AssistantBrainController, Crm::AssistantChatController, Crm::AssistantChatOwnershipsController, Crm::AssistantChatSharesController, Crm::AssortmentInstructionsController, Crm::AuditTrailsController, Crm::BankBalanceStatementsController, Crm::BasecampOauthController, Crm::BlogImageChecksController, Crm::CarriersController, Crm::CertificationsController, Crm::CharitiesController, Crm::CommissionRatesController, Crm::CompanyHolidaysController, Crm::ContactTrainingTopicsController, Crm::ContentLinksController, Crm::CourseEnrollmentsController, Crm::CoursesController, Crm::CustomerOutletPurchasesController, Crm::Customers::OnboardingController, Crm::CycleCountsController, Crm::EdiCommunicationLogsController, Crm::ElementPoleAssignmentsController, Crm::EmailRenderHarnessController, Crm::EmployeeAccountController, Crm::EventsController, Crm::ExportedCatalogItemPacketsController, Crm::FloorPlanDisplaysController, Crm::GenerateBarcodesController, Crm::GenerateCartonLabelsController, Crm::ImageProfileManagerController, Crm::ImageProfilesController, Crm::InventoryCommitsController, Crm::IqAccessoryFiltersController, Crm::ItemDemandForecastAdditionsController, Crm::Items::CustomMatsController, Crm::Items::PriceListsController, Crm::KpisController, Crm::LiabilityInsurancesController, Crm::LinkChecksController, Crm::ListingIssuesController, Crm::LiveEventsController, Crm::LoginActivitiesController, Crm::MenardInventoryController, Crm::MetricsAnalysisController, Crm::MicrosoftAdsOauthController, Crm::NavbarDropdownsController, Crm::NewCustomersController, Crm::OpportunityBriefingsController, Crm::OpportunityLookupController, Crm::OrderDashboardController, Crm::OutboundCallsController, Crm::PackingsController, Crm::PartyLookupController, Crm::PartyResearchFindingsController, Crm::PartyResearchRunsController, Crm::PaymentsController, Crm::PhonePopupController, Crm::PinterestOauthController, Crm::PostCommentsController, Crm::PostRevisionsController, Crm::PostsController, Crm::PricingProgramAssignersController, Crm::PrintProfilesController, Crm::PrintersController, Crm::PublicationsController, Crm::QueueCoveragesController, Crm::QuickEstimatorsController, Crm::QuickSearchController, Crm::RedactorAiController, Crm::RedactorFaqPickerController, Crm::RedactorImagePickerController, Crm::RedactorProductPickerController, Crm::RedactorVideoPickerController, Crm::Reports::AccountingRecordsController, Crm::Reports::ActivityPerformanceController, Crm::Reports::BalanceSheetController, Crm::Reports::BookOfBusinessController, Crm::Reports::CallBreakdownController, Crm::Reports::CallStatisticsController, Crm::Reports::CampaignsReportController, Crm::Reports::CashFlowController, Crm::Reports::ChannelRevenueController, Crm::Reports::ConversionReportController, Crm::Reports::CostCenterController, Crm::Reports::CouponSalesReportController, Crm::Reports::CustomerPerformanceController, Crm::Reports::GrossSalesReportController, Crm::Reports::ItemMovedToScrapReportController, Crm::Reports::ItemSaleController, Crm::Reports::ItemsSpecMatrixController, Crm::Reports::KpiCallController, Crm::Reports::KpiTimeOnTaskController, Crm::Reports::LeadReportController, Crm::Reports::MissedCallsController, Crm::Reports::OpportunitiesReportController, Crm::Reports::OpportunitiesVsLogisticsController, Crm::Reports::OrdersReportController, Crm::Reports::PhoneQueueReportController, Crm::Reports::PresenceController, Crm::Reports::ProfileDiscountController, Crm::Reports::ProfitLossController, Crm::Reports::ReconciliationController, Crm::Reports::ReportsController, Crm::Reports::RmasReportController, Crm::Reports::SalesCommissionsController, Crm::Reports::SalesProfitController, Crm::Reports::SalesRepRankingController, Crm::Reports::ShippingRatesController, Crm::Reports::SmartServicesController, Crm::Reports::SourcesReportController, Crm::Reports::StatusTimelineReportController, Crm::Reports::TechCallsReportController, Crm::Reports::TechProductivityController, Crm::Reports::WebSitePerformanceController, Crm::RetailersController, Crm::ReviewsIoController, Crm::RmaDashboardController, Crm::RmaItemsController, Crm::RoomPlansController, Crm::SalesCommissionsController, Crm::Scheduler::BookingPageQuestionsController, Crm::Scheduler::BookingPagesController, Crm::Scheduler::BookingsController, Crm::Scheduler::DashboardController, Crm::Scheduler::ProfilesController, Crm::SeoKeywordsController, Crm::SeoOverviewController, Crm::SettingsController, Crm::ShowcasesController, Crm::SiteMapRecommendationsController, Crm::SiteMapsController, Crm::SmsBlocksController, Crm::SmsMessagesController, Crm::SpeedeeManifestsController, Crm::StorageLocationsController, Crm::SurveyEnrollmentsController, Crm::SurveysController, Crm::TagsController, Crm::TechBenchController, Crm::TimeOffBalancesController, Crm::TimeOffBlockedDaysController, Crm::TimeOffPoliciesController, Crm::TimeOffRequestsController, Crm::TimeOffTypesController, Crm::TimeOffsController, Crm::TradeShowsController, Crm::TranslationKeysController, Crm::TranslationsController, Crm::VariableCostsController, Crm::WarehousesController, Crm::WarrantiesController, Crm::Wayfair::SchemasController, Crm::WebhookLogsController, Crm::WorkSchedulesController, Crm::XrateAveragesController, Crm::YouTubeOauthController, CrmNavbarPresenceController, CustomerDropEventsController, CustomerFiltersController, CustomerShippingAccountNumbersController, CustomerTopicsController, CustomersController, DailyFocusController, DashboardsController, DataDictionarySetsController, DataImportCellsController, DataImportsController, DeliveriesController, DesignToolFixturesController, DiscountsController, DoNotCallsController, EmailPreferencesController, EmailTemplatesController, EmployeeGoalsController, EmployeePhoneStatusesController, EmployeeReviewsController, EmployeeTopicsController, EmployeesController, GeneratedImagesController, GeneratedPdfsController, HeatingElementProductLineOptionsController, IdentificationNumbersController, ImagesController, InvoicesController, ItAssetsController, ItemLedgerEntriesController, ItemsController, JobsController, LedgerAccountsController, LedgerClosingPeriodsController, LedgerCompanyAccountsController, LedgerEntriesController, LedgerProjectsController, LedgerTransactionsController, LineItemsController, LocatorBlackListPartiesController, LocatorWhiteListPartiesController, MailActivitiesController, MailingsController, MenusController, OppFunnelsController, OpportunitiesController, OrdersController, OutgoingPaymentsController, PackagingsController, PhoneMiscellaneousController, PhoneQueueOrderChangesController, PhoneQueueRotationsController, PickItemsController, PraisesController, ProductCategoriesController, ProductLinesController, ProductSpecificationsController, ProfilesController, PurchaseOrderShipmentsController, PurchaseOrdersController, QueueCallLogsController, QuotesController, ReceiptsController, RevenuesController, RmaReasonCodesController, RmasController, RolesController, RoomConfigurationsController, SalesForecastsController, SalesGoalsController, SalesRepQueueEntriesController, SalesRepQueuesController, SearchesController, SerialNumbersController, ShipmentReceiptsController, ShipmentsController, SourcesController, SpiffEnrollmentsController, SpiffsController, SqlReposController, StandaloneDeliveriesController, StatementOfAccountsController, StoreItemsController, StoreTransfersController, StoresController, StrengthsController, SupplierItemsController, SuppliersController, SupportCasesController, TaxExemptionsController, TaxRatesController, TopicCategoriesController, TopicExamsController, TopicsController, UploadsController, VariantGroupsController, VideosController, VisitsController, VouchersController, WarehousePackagesController

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 ApplicationController

#account_impersonated?, #add_to_flash, #after_sign_in_path_for, #bypass_forgery_protection?, #chat_enabled?, #cloudflare_cleared?, #default_catalog, #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

#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

#access_denied(exception) ⇒ void

This method returns an undefined value.

Handles CanCan::AccessDenied by flashing the denial and redirecting to the CRM home.

Parameters:

  • exception (CanCan::AccessDenied, nil)

    the raised exception



112
113
114
115
116
117
# File 'app/controllers/crm_controller.rb', line 112

def access_denied(exception)
  generic_message = 'You are not authorized to perform that action.'
  exception&.default_message = generic_message
  flash[:error] = exception&.message.presence || generic_message
  redirect_back_or_to(crm_home_path)
end

#context_idString?

The id param matching the current context_type.

Returns:

  • (String, nil)

    the context record id



191
192
193
# File 'app/controllers/crm_controller.rb', line 191

def context_id
  params["#{params[:context_type].to_s.downcase.singularize}_id"]
end

#context_object(*finder_options) ⇒ ApplicationRecord?

Resolves the context record from context_type/context_id or a *_id param.

Parameters:

  • finder_options (Array<Object>)

    extra options passed to the finder

Returns:



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'app/controllers/crm_controller.rb', line 171

def context_object(*finder_options)
  if params[:context_type].present?
    begin
      context_class(params.expect(:context_type))&.find(context_id, *finder_options)
    rescue StandardError
      nil
    end
  elsif (k = params.keys.find { |k| k.end_with?('_id') }) # Guess based on what param with _id is presented
    mk = k.scan(/(.*)_id\z/).join
    begin
      context_class(mk)&.find(params.expect(k.to_sym))
    rescue StandardError
      nil
    end
  end
end

#crm_home_path(employee = nil) ⇒ String

CRM home path - redirects to company or employee dashboard

Parameters:

  • employee (Employee, nil) (defaults to: nil)

    the employee whose dashboard to target (defaults to the current user)

Returns:

  • (String)

    the dashboard path



210
211
212
213
214
215
216
217
# File 'app/controllers/crm_controller.rb', line 210

def crm_home_path(employee = nil)
  employee ||= current_user
  if employee.nil? || (employee.try(:employee_record).try(:default_dashboard) == 'company')
    dashboard_path
  else
    employee_dashboard_path(employee.id)
  end
end

#current_abilityCrmAbility

The CanCan ability for the current CRM user.

Returns:



22
23
24
# File 'app/controllers/crm_controller.rb', line 22

def current_ability
  @current_ability ||= CrmAbility.new(current_user)
end

#default_url_options(options = {}) ⇒ Hash

CRM routes have no locale prefix, so injecting locale: into URL options
would append ?locale=en-US as a query param instead of a path segment.

Parameters:

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

    Extra URL options to merge in

Options Hash (options):

  • locale (String)

    Stripped out — CRM routes have no locale prefix

Returns:

  • (Hash)

    URL options with https protocol and no locale



43
44
45
# File 'app/controllers/crm_controller.rb', line 43

def default_url_options(options = {})
  { protocol: 'https' }.merge(options.except(:locale))
end

#download_tempObject

Used by route rule match '/tempfile/:file_name', to: 'crm#download_temp', via: %i[get post], as: :tempfile_download
Finds the file in the current user's temp directory and send it via accelerated download



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'app/controllers/crm_controller.rb', line 78

def download_temp
  file_name = params[:file_name].presence
  return render_404 unless file_name

  file_name = ActiveStorage::Filename.new(file_name).sanitized
  file_format = params[:format].presence
  file_name = "#{file_name}.#{ActiveStorage::Filename.new(file_format).sanitized}" if file_format

  file_path = Rails.root.join(Rails.application.config.x.temp_storage_path.to_s, 'users', current_user.id.to_s, file_name)

  unless File.exist?(file_path)
    flash[:error] = 'File not found or has expired.'
    redirect_back_or_to(root_path)
    return
  end

  logger.info "Sending File #{file_path} to user"
  expires_now
  send_file_accelerated(file_path, download: true)
end

#get_tempfile_path_for_download(file_name = nil) ⇒ Hash

Generates a tempfile location for the current user, creates the directory if needed, returns the local file path and request path
to get to the file via download_temp

Parameters:

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

    the file name to place in the user's temp directory

Returns:

  • (Hash)

    local_file_path and request_path for the download



52
53
54
55
56
57
58
59
# File 'app/controllers/crm_controller.rb', line 52

def get_tempfile_path_for_download(file_name = nil)
  local_directory_path = Rails.root.join(Rails.application.config.x.temp_storage_path.to_s, 'users', current_user.id.to_s)
  FileUtils.mkdir_p(local_directory_path)
  {
    local_file_path: "#{local_directory_path}/#{file_name}",
    request_path: "/tempfile/#{file_name}"
  }.freeze
end

#init_status_job_collectorvoid

This method returns an undefined value.

Background-job tracking. Every status-tracked worker (Sidekiq::Status::Worker,
e.g. via Workers::StatusBroadcastable) enqueued during this request is
collected by Sidekiq::TrackEnqueuedStatusJobsMiddleware into
CurrentScope.enqueued_status_jobs, then handed to the global Jobs offcanvas.
Redirects carry the entries through flash; Turbo Stream renders append the
bridge to the current page immediately.



136
137
138
# File 'app/controllers/crm_controller.rb', line 136

def init_status_job_collector
  CurrentScope.enqueued_status_jobs ||= []
end

#initialize_crm_lazy_chunksObject

Note:

Lazy loading is now handled by Stimulus controllers



163
164
165
# File 'app/controllers/crm_controller.rb', line 163

def initialize_crm_lazy_chunks
  # No-op - kept for compatibility with any before_action references
end

#persist_enqueued_status_jobsvoid

This method returns an undefined value.

Drains the request's collected status jobs into either the current Turbo
Stream response or flash[:tracked_jobs] for the next full-page render.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'app/controllers/crm_controller.rb', line 144

def persist_enqueued_status_jobs
  jobs = CurrentScope.enqueued_status_jobs
  return if jobs.blank?

  if response.media_type == Mime[:turbo_stream].to_s
    bridge = render_to_string(partial: '/shared/tracked_jobs', locals: { tracked_jobs: jobs })
    stream = turbo_stream.append('tracked-job-bridges', bridge)
    self.response_body = [response_body, stream].join
    return
  end

  # Persistent flash (NOT flash.now): the enqueuing request usually redirects,
  # and the jobs must survive to the redirect target's render.
  # rubocop:disable Rails/ActionControllerFlashBeforeRender
  flash[:tracked_jobs] = (Array(flash[:tracked_jobs]) + jobs).uniq { |entry| entry['jid'] }
  # rubocop:enable Rails/ActionControllerFlashBeforeRender
end

#record_not_found(error) ⇒ void

This method returns an undefined value.

Handles ActiveRecord::RecordNotFound by flashing and redirecting to the CRM home.

Parameters:

  • error (ActiveRecord::RecordNotFound)

    the raised exception



103
104
105
106
# File 'app/controllers/crm_controller.rb', line 103

def record_not_found(error)
  flash[:error] = error.message
  redirect_back_or_to crm_home_path
end

#redirect_to_job_or_fallback(job_id, fallback_path, duplicate_lookup: nil, notice: nil) ⇒ void

This method returns an undefined value.

Redirects to job status page if job was queued, otherwise redirects to fallback path with error message
Use when calling perform_async which may return nil if job was deduplicated or failed to queue

When +duplicate_lookup+ is provided (e.g. SidekiqUniqueJobsJidLookup for the same worker args),
we try to send the user to the already-queued or running job — +perform_async+ does not return
that jid when sidekiq-unique-jobs rejects on conflict.
+notice+ is the success-path flash, for call sites that used to write
redirect_to job_path(jid), notice: '…'. It is dropped on the fallback
branch, where the error flash is the honest message.

Parameters:

  • job_id (String, nil)

    the jid returned by perform_async

  • fallback_path (String)

    where to redirect when no job was queued

  • duplicate_lookup (#call, nil) (defaults to: nil)

    optional lookup for an already-queued duplicate jid

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

    flash notice for the success redirect



242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'app/controllers/crm_controller.rb', line 242

def redirect_to_job_or_fallback(job_id, fallback_path, duplicate_lookup: nil, notice: nil)
  if job_id.present?
    redirect_to job_path(job_id), **{ notice: notice }.compact
  elsif duplicate_lookup && (existing_jid = duplicate_lookup.call).present?
    flash[:notice] = 'That action is already running or queued. Showing its job status.'
    redirect_to job_path(existing_jid)
  else
    flash[:error] = 'Could not queue a new job. If you did not just start the same action, a stale ' \
                    'uniqueness lock in Redis may be blocking new jobs — clear it in Sidekiq Unique Jobs ' \
                    'admin or wait for the orphan reaper.'
    redirect_to fallback_path
  end
end

#render_edit_action(status: nil) ⇒ void

This method returns an undefined value.

Render edit action with optional section support.

Defaults to no explicit status so successful GET edit actions return 200.
Validation-failure call sites (update/create error paths) should explicitly
pass status: :unprocessable_content so Turbo can render the form errors.

Parameters:

  • status (Symbol, Integer, nil) (defaults to: nil)

    HTTP status for the render



264
265
266
267
268
269
270
# File 'app/controllers/crm_controller.rb', line 264

def render_edit_action(status: nil)
  if params[:section].present?
    render "edit_#{params[:section]}", status: status
  else
    render 'edit', status: status
  end
end

#set_context(object) ⇒ Object

Set context object for the current view

Parameters:

  • object (Object)

    the context object to memoize

Returns:

  • (Object)

    the memoized context object



223
224
225
# File 'app/controllers/crm_controller.rb', line 223

def set_context(object)
  @set_context ||= object
end

#set_download_pathvoid

This method returns an undefined value.

Moves the one-shot download path/disposition out of the session into ivars.



122
123
124
125
126
127
# File 'app/controllers/crm_controller.rb', line 122

def set_download_path
  @download_path ||= session[:download_path]
  @download_disposition ||= session[:download_disposition]
  session[:download_path] = nil
  session[:download_disposition] = nil
end

#stash_file_for_temp_download(file_path) ⇒ String

Moves a file to a dedicated download directory for the current user, returns the request path for the user to get to the file via
their browser, use in conjunction with the download_temp

Parameters:

  • file_path (String)

    path of the file to move into the user's temp directory

Returns:

  • (String)

    the request path for downloading the stashed file



66
67
68
69
70
71
72
73
74
# File 'app/controllers/crm_controller.rb', line 66

def stash_file_for_temp_download(file_path)
  file_name = File.basename(file_path)
  file_name = ActiveStorage::Filename.new(file_name).sanitized # Ensures we have a sanitized file name
  res = get_tempfile_path_for_download(file_name)
  local_file_path = res[:local_file_path]
  # If the file isn't already in the target location, move it there so that download accelerated can work
  FileUtils.mv(file_path, local_file_path) unless File.identical?(file_path, local_file_path)
  res[:request_path]
end

Refresh the apex-domain "admin presence" cookie so sibling apps (www, etc.)
can show admin-only UI without a second login. Slid on every CRM hit; falls
back to clearing if the actor isn't an eligible admin. Use +true_account+
so a masquerading employee keeps the cookie tied to their employee identity.



276
277
278
279
280
281
# File 'app/controllers/crm_controller.rb', line 276

def sync_admin_presence_cookie
  actor = (respond_to?(:true_account) && ) || 
  AdminPresence.sync!(cookies, actor)
rescue StandardError => e
  ErrorReporting.from_controller(self).warning(e)
end

#touch_employee_last_seenObject

Record which IP the employee's latest CRM request came from, feeding the
office/remote line on the who's-working grid (EmployeeLastSeen). One cache
write per request; never allowed to break the response.



286
287
288
289
290
# File 'app/controllers/crm_controller.rb', line 286

def touch_employee_last_seen
  EmployeeLastSeen.touch(current_user&.id, request.remote_ip)
rescue StandardError => e
  ErrorReporting.from_controller(self).warning(e)
end