Class: OrdersController
- Inherits:
-
CrmController
- Object
- ActionController::Base
- ApplicationController
- CrmController
- OrdersController
- Includes:
- Controllers::ActivitiesTab, Controllers::CommunicationsTab, Controllers::Crm::ShippingParams, Controllers::OrdersTab, Controllers::PriceEditable, Controllers::RequireTurboFrame, Controllers::RoomsTab, Controllers::SmsTab, Controllers::UploadsTab, Controllers::WarehouseStreamActions, Controllers::Workflowable, CrmFormHelper
- Defined in:
- app/controllers/orders_controller.rb
Overview
Controller: orders.
Constant Summary collapse
- TAB_ACTIONS =
Tab fragments never render standalone — non-frame hits redirect to show ?tab=.
%i[tab_material_alerts tab_line_items tab_main tab_contacts tab_shipping tab_rooms tab_attachments tab_communications tab_sms tab_activities tab_payments tab_tickets tab_inventory tab_invoices tab_edi_documents tab_rmas tab_credit_memos tab_reviews tab_marketing tab_warranty].freeze
Constants included from Controllers::WarehouseStreamActions
Controllers::WarehouseStreamActions::WAREHOUSE_TAB_CONTENT_FRAME
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
-
#account_managers ⇒ void
Renders the account-managers (reps/contact/opportunity) edit screen.
-
#account_managers_defined ⇒ void
Saves the account-managers form: reps, contact, and a new linked opportunity, syncing the shipping address/tracking email from the contact.
-
#approve_credit_request ⇒ void
Approves the order's credit request and increases available credit.
-
#cancel ⇒ void
Cancels the order, or destroys it outright when it has no history.
-
#cancel_cod_check ⇒ void
Clears COD collection by check and recalculates shipping.
-
#cancel_cod_no_check ⇒ void
Clears COD collection without check and recalculates shipping.
-
#choose_shipping_method ⇒ void
Saves the shipping-method selection (plus uploaded label documents) via
Shipping::UpdateShippingMethodand advances the order toward payment. -
#cod_check ⇒ void
Sets COD collection by check and recalculates shipping.
-
#cod_no_check ⇒ void
Sets COD collection without check and recalculates shipping.
-
#confirm_serial_numbers ⇒ void
Saves serial-number reservations and releases the order once reservations are complete.
-
#contact_lookup ⇒ Object
Used by tom-select field on order/:id/account_managers if q is specified a global lookup is run if party_id is specified, then a single party is looked up (used to initialize form on load typically).
-
#create ⇒ Object
PUT /customers/1/orders.
-
#deny_credit_request ⇒ void
Denies the order's credit request and notifies the rep.
-
#destroy ⇒ Object
DELETE /orders/1.
-
#disable_auto_coupon ⇒ void
Disables auto-coupons on the order and refreshes the discount summary.
-
#do_move ⇒ void
Moves the order to another customer/opportunity via
Order::Mover. -
#edi_force_price_match ⇒ void
Forces the order's prices to match its EDI pricing, refreshing the line-items grid and discount summary.
-
#edit ⇒ Object
GET /customers/1/orders/1/edit.
-
#edit_sales_support_rep ⇒ void
Renders the sales-support-rep editor.
-
#enable_auto_coupon ⇒ void
Re-enables auto-coupons on the order, recalculates discounts, and refreshes the discount summary.
-
#enter_rooms ⇒ void
Enqueues the worker that enters the selected room configurations onto the order, redirecting to the job page.
-
#exclude_from_payment_check ⇒ void
Excludes the order from the payment check.
-
#fix_catalog ⇒ void
Re-maps the order's catalog items after a catalog change and flashes the per-item results.
-
#force_invoiced_status ⇒ void
Forces the order to invoiced status (admin escape hatch for orders stuck in pending payment after all deliveries invoiced).
-
#get_details ⇒ void
Returns order details (room ids, goods line items, product lines) as JSON.
-
#get_spiff_enrollments ⇒ void
Loads the selected contact's active spiff enrollment for the spiff form.
-
#include_in_payment_check ⇒ void
Re-includes the order in the payment check.
-
#index ⇒ Object
GET /customers/1/orders.
-
#lookup ⇒ void
Order autocomplete/search endpoint (JSON for TomSelect, HTML partial for lookup suggestions), honoring state, customer, and wildcard filters.
-
#lookup_row ⇒ Object
Return a server-rendered order row for the support case orders table.
-
#move ⇒ void
Renders the move-order form.
-
#new ⇒ Object
GET /customers/1/orders/new.
-
#pick_serial_numbers ⇒ void
Renders the serial-number picking screen, auto-reserving serial numbers first.
-
#place_cr_hold ⇒ void
Puts the order on CR hold under an advisory lock, optionally routing to stock reservation when
reserve_stockis set. -
#process_spiff ⇒ void
Marks the order's spiff as paid (accounting reps only).
-
#profit_margins ⇒ void
Renders the profit-margins editor.
-
#recalculate_discount ⇒ void
Recalculates the order's discounts and refreshes the line-items grid and discount summary.
-
#recalculate_taxes ⇒ void
Refreshes the order's tax rate (disabled for CI-invoice credit orders) and refreshes the line-items grid and discount summary.
-
#release_back_order ⇒ void
Releases a back-ordered order, detouring to serial-number reservation when required.
-
#release_cr_hold ⇒ void
Releases the order from CR hold under an advisory lock.
-
#release_management_hold ⇒ void
Releases the order from management hold.
-
#resend_google_offline_conversion ⇒ void
Re-sends the Google Ads offline conversion for the order and flashes the result details.
-
#resend_pinterest_conversion ⇒ void
Re-sends the Pinterest conversion for the order and flashes the result details.
-
#resend_review_request ⇒ void
Re-queues the Reviews.io invitation for the order.
-
#restore ⇒ void
Restores a cancelled order.
-
#review_credit_request ⇒ void
Renders the credit-request review screen, redirecting away when the request was already processed.
-
#review_echeck_request ⇒ void
Renders the e-check authorization review screen, redirecting away when the order was already processed.
-
#rooms ⇒ void
Renders the rooms step, preloading all room configurations available to the order and its opportunity.
-
#send_public_payment_link ⇒ void
Starts a new ORDER_PAYMENT communication (public payment link) for the order, pre-addressed to the given email.
-
#send_tracking_email ⇒ void
Sends the tracking (or ready-for-pickup) email for the order.
-
#service ⇒ void
Renders the service-scheduling step for orders containing schedulable services.
-
#set_shipping_address ⇒ void
Saves the shipping-address selection (address-book pick, one-time-address update, or new address) and proceeds to item picking.
-
#setup_service ⇒ void
Creates or links the SmartService support case for the order's schedulable services and advances the order to pending payment.
-
#ship_confirm_service_deliveries ⇒ void
Ship-confirms all service deliveries on the order that are ready to fulfill.
-
#shipping ⇒ void
Renders the shipping step, defaulting label instructions, phone, and tracking email; requires a shipping address first.
-
#shipping_address ⇒ void
Renders the shipping-address step, defaulting the address and phone from the customer/contact and locking edits when payments are authorized.
-
#show ⇒ Object
GET /customers/1/orders/1 Accepts ID or reference_number (e.g., SO123456).
-
#split ⇒ void
Renders the split-order form.
-
#split_back_order_all ⇒ void
Moves the entire order to back order.
-
#split_selected ⇒ void
Splits the selected line items into a back order via
Order::Splitter. -
#tab_activities ⇒ void
Renders the activities tab fragment for the order.
-
#tab_attachments ⇒ void
Renders the attachments tab fragment for the order.
-
#tab_communications ⇒ void
Renders the communications tab fragment for the order.
-
#tab_contacts ⇒ void
Renders the contacts tab fragment for the order.
-
#tab_credit_memos ⇒ void
Renders the credit-memos tab fragment for the order.
-
#tab_edi_documents ⇒ void
Renders the EDI documents tab fragment, loading the order's EDI communication logs.
-
#tab_inventory ⇒ void
Renders the inventory tab fragment: remaining-to-ship item groups.
-
#tab_invoices ⇒ void
Renders the invoices tab fragment for the order.
-
#tab_line_items ⇒ void
Renders the line-items tab fragment for the order.
-
#tab_main ⇒ void
Renders the main tab fragment for the order.
-
#tab_marketing ⇒ void
Renders the marketing tab fragment for the order.
-
#tab_material_alerts ⇒ void
Renders the material-alerts tab fragment for the order.
-
#tab_payments ⇒ void
Renders the payments tab fragment for the order.
-
#tab_reviews ⇒ void
Renders the reviews tab fragment, loading Reviews.io data for the order.
-
#tab_rmas ⇒ void
Renders the RMAs tab fragment for the order.
-
#tab_rooms ⇒ void
Renders the rooms tab fragment for the order.
-
#tab_shipping ⇒ void
Renders the shipping tab fragment for the order.
-
#tab_sms ⇒ void
Renders the SMS tab fragment for the order.
-
#tab_tickets ⇒ void
Renders the tickets tab fragment for the order.
-
#tab_warranty ⇒ void
Renders the warranty tab fragment, loading the order's warranties.
-
#update ⇒ Object
PUT /customers/1/orders/1.
-
#update_profit_margins ⇒ void
Saves the order's minimum profit markup, attempting release from profit review when margins now pass.
-
#update_sales_support_rep ⇒ void
Saves the sales support rep and commission date.
Methods included from CrmFormHelper
#blocking_submit_button, #boolean_select, #datalist, #edit_button, #form_style_attribute_display, #opportunity_local_sales_rep_input, #sales_support_rep_input, #submit_cancel, #technical_rep_input, #technical_rep_sec_input, #yes_no_blank_boolean_collection_for_select, #yes_no_boolean_collection_for_select
Methods included from Controllers::PriceEditable
Methods included from Controllers::WarehouseStreamActions
Methods included from FileDownloadPresenter
Methods included from Controllers::RequireTurboFrame
require_in_pane_tab_frames, require_turbo_frame
Methods included from Controllers::Workflowable
#render_workflow_error_stream, #render_workflow_success_stream, #workflow_action, #workflow_action_complete
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
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 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
#account_managers ⇒ void
This method returns an undefined value.
Renders the account-managers (reps/contact/opportunity) edit screen.
192 193 194 |
# File 'app/controllers/orders_controller.rb', line 192 def account_managers set_account_manager_edit_fields end |
#account_managers_defined ⇒ void
This method returns an undefined value.
Saves the account-managers form: reps, contact, and a new linked
opportunity, syncing the shipping address/tracking email from the contact.
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 |
# File 'app/controllers/orders_controller.rb', line 249 def account_managers_defined @order.attributes = params[:order] (:update, @order) if @order.save res = @order.fix_future_release_date flash[:info] = res[:message] if res[:message].present? # because of the weird way combo_contact sets contacts, and that we can also create an opportunity from the same form, we want to update a new opportunity with the new contact as well... but only if it's new... otherwise let the chips fall... ie you can get into a situation where an order is linked to one contact, but also linked to an opp with another contact... yeesh @order.opportunity.update(contact_id: @order.contact_id) if @order.contact && params[:order][:opportunity_attributes] && params[:order][:opportunity_attributes][:name].present? && @order.opportunity Rails.logger.debug { "@order.update_shipping_address_with_contact: #{@order.update_shipping_address_with_contact}" } if @order.update_shipping_address_with_contact Rails.logger.debug '@order.update_shipping_address_with_contact IS TRUE!!!' if @order.contact.present? @order.shipping_address&.person_name_override = @order.contact.name @order.shipping_address&.save @order.tracking_email = [@order.contact.email] if @order.contact.email.present? && @order.tracking_email.none?(@order.contact.email) @order.shipping_phone = @order.contact.phone else # contact reset but ant to update the order shipping address and phone and tracking email, so reset @order.shipping_address&.person_name_override = nil @order.shipping_address&.save @order.set_default_tracking_email(force: true) @order.shipping_phone = @order.customer.phone || @order.customer.cell_phone end @order.save end redirect_to_return_path_or_default(shipping_address_order_url(@order)) else flash.now[:error] = "There were errors updating the order: #{@order.errors_with_deliveries_errors.to_sentence.capitalize}" set_account_manager_edit_fields render :account_managers, status: :unprocessable_content end end |
#approve_credit_request ⇒ void
This method returns an undefined value.
Approves the order's credit request and increases available credit.
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 |
# File 'app/controllers/orders_controller.rb', line 1302 def approve_credit_request :approve_credit_request, Order @order = Order.find(params[:id]) @customer = @order.customer @billing_entity = @order.billing_entity @billing_entity.approve_credit_request(@order.balance, @order) @order.approve_credit_request flash[:info] = 'Credit available increased and rep notified.' redirect_to_return_path_or_default @order end |
#cancel ⇒ void
This method returns an undefined value.
Cancels the order, or destroys it outright when it has no history.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'app/controllers/orders_controller.rb', line 148 def cancel customer = @order.customer success = @order.cancel_or_destroy if success @order = Order.find_by(id: @order.id) flash[:info] = if @order 'Order has been cancelled.' else 'Order was deleted' end elsif @order&.errors_with_deliveries_errors&.any? flash[:error] = @order.errors_with_deliveries_errors.join(', ') end if @order redirect_to_return_path_or_default order_path(@order) else redirect_to_return_path_or_default customer_path(customer) end end |
#cancel_cod_check ⇒ void
This method returns an undefined value.
Clears COD collection by check and recalculates shipping.
475 476 477 478 479 480 481 |
# File 'app/controllers/orders_controller.rb', line 475 def cancel_cod_check @order.need_to_recalculate_shipping @order.update(cod_collection_type: nil) result = eval(@order.last_shipping_rate_request_result.to_s) # rubocop:disable Security/Eval handle_shipping_flash_messaging(result, 'cancel_cod_check') redirect_to action: :shipping, id: @order.id, customer_id: @order.customer.id, return_path: @return_path end |
#cancel_cod_no_check ⇒ void
This method returns an undefined value.
Clears COD collection without check and recalculates shipping.
521 522 523 524 525 526 527 |
# File 'app/controllers/orders_controller.rb', line 521 def cancel_cod_no_check @order.need_to_recalculate_shipping @order.update(cod_collection_type: nil) result = eval(@order.last_shipping_rate_request_result.to_s) # rubocop:disable Security/Eval handle_shipping_flash_messaging(result, 'cancel_cod_no_check') redirect_to action: :shipping, id: @order.id, customer_id: @order.customer.id, return_path: @return_path end |
#choose_shipping_method ⇒ void
This method returns an undefined value.
Saves the shipping-method selection (plus uploaded label documents) via
Shipping::UpdateShippingMethod and advances the order toward payment.
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 |
# File 'app/controllers/orders_controller.rb', line 532 def choose_shipping_method if @order.editing_locked? flash[:error] = "Can't choose shipping method on order that is locked. Please CR HOLD to change shipping method." redirect_to_return_path_or_default(order_url(@order)) else # puts "choose_shipping_method: params: #{params.inspect}" @ship_quotable = @order %i[custom_packing_slip_upload master_carton_label_upload manual_ship_label_upload bol_upload].each do || next if params.dig(, :attachment).blank? @order.uploads.build(params[]) end # Use service to handle shipping updates and discount recalculation # Get the order-specific parameters (empty hash if no order params) order_params = shipping_params # If there are no order parameters, just redirect (no shipping to update) if order_params.empty? redirect_to_return_path_or_default(order_url(@order)) return end # Pass the order parameters to the service result = Shipping::UpdateShippingMethod.new.update_from_params(@order, { order: order_params }) if result.success? # Display any shipping change messages result..each { |msg| flash[:info] = msg } if result..present? # If "Purchase label early" checkbox was checked, show confirmation message # The actual label purchase will happen when the order reaches awaiting_deliveries state # (triggered by after_transition hook in Order model) manual_label_uploaded = params.dig(:manual_ship_label_upload, :attachment).present? if @order.purchase_label_early? && !manual_label_uploaded && @order.walmart_sww_eligible? flash[:info] = 'Shipping label will be purchased automatically when the order is released to the warehouse. Tracking will be sent to Walmart immediately.' end res = @order.fix_future_release_date add_to_flash(res[:message]) if res[:message].present? if @order.includes_schedulable_service? && @order.smartservice_ticket.nil? redirect_to_return_path_or_default(service_order_url(@order)) else @order.pending_payment if @order.awaiting_deliveries? # already had payment so it went straight to warehouse # Check for early label purchase result early_label_result = @order. flash[early_label_result[:type]] = early_label_result[:message] if early_label_result.present? redirect_to_return_path_or_default(order_url(@order)) elsif @order.profit_review? flash[:warning] = 'Order profit not met' redirect_to_return_path_or_default(order_url(@order)) else redirect_to_return_path_or_default(order_discounts_url(@order)) end end else flash.now[:error] = result.errors render :shipping, status: :unprocessable_content end end end |
#cod_check ⇒ void
This method returns an undefined value.
Sets COD collection by check and recalculates shipping.
465 466 467 468 469 470 471 |
# File 'app/controllers/orders_controller.rb', line 465 def cod_check @order.need_to_recalculate_shipping @order.update(cod_collection_type: 'check') result = eval(@order.last_shipping_rate_request_result.to_s) # rubocop:disable Security/Eval handle_shipping_flash_messaging(result, 'cod_check') redirect_to action: :shipping, id: @order.id, customer_id: @order.customer.id, return_path: @return_path end |
#cod_no_check ⇒ void
This method returns an undefined value.
Sets COD collection without check and recalculates shipping.
485 486 487 488 489 490 491 |
# File 'app/controllers/orders_controller.rb', line 485 def cod_no_check @order.need_to_recalculate_shipping @order.update(cod_collection_type: 'no_check') result = eval(@order.last_shipping_rate_request_result.to_s) # rubocop:disable Security/Eval handle_shipping_flash_messaging(result, 'cod_no_check') redirect_to action: :shipping, id: @order.id, customer_id: @order.customer.id, return_path: @return_path end |
#confirm_serial_numbers ⇒ void
This method returns an undefined value.
Saves serial-number reservations and releases the order once reservations
are complete.
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 |
# File 'app/controllers/orders_controller.rb', line 1038 def confirm_serial_numbers @order = Order.find(params[:id]) if @order.update(params[:order]) if @order.needs_serial_number_reservation? if @order.has_incomplete_reservations? flash.now[:error] = 'Serial Number reservation must be completed before releasing' load_line_items_requiring_reservation render :pick_serial_numbers, status: :unprocessable_content else @order.release_order flash[:info] = 'Order released' redirect_to_return_path_or_default order_path(@order) end else redirect_to_return_path_or_default order_path(@order) end else flash.now[:error] = @order.errors_to_s.presence || 'Could not confirm serial numbers.' load_line_items_requiring_reservation render :pick_serial_numbers, status: :unprocessable_content end end |
#contact_lookup ⇒ Object
Used by tom-select field on order/:id/account_managers
if q is specified a global lookup is run
if party_id is specified, then a single party is looked up (used to initialize form on load typically)
1270 1271 1272 1273 1274 |
# File 'app/controllers/orders_controller.rb', line 1270 def contact_lookup @order = Order.find(params[:id]) result = Order::ContactLookup.new.process(@order, params) render json: { results: result.results, total: result.total_entries } end |
#create ⇒ Object
PUT /customers/1/orders
124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'app/controllers/orders_controller.rb', line 124 def create @order = Order.new(params[:order].merge(customer_id: @customer.id, shipping_method: @customer.default_shipping_option_name)) @order.single_origin = true if @customer.is_direct_buy? # patch for now for Direct Buy, must be single origin if @order.valid? (:create, @order) @order.pending_payment! flash[:error] = "Order shipping address not valid or otherwise shipping not set! Can't proceed until it is corrected." unless @order.pending_payment? redirect_to_return_path_or_default confirm_and_pay_order_path(@order) else render action: :new, status: :unprocessable_content end end |
#deny_credit_request ⇒ void
This method returns an undefined value.
Denies the order's credit request and notifies the rep.
1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 |
# File 'app/controllers/orders_controller.rb', line 1315 def deny_credit_request :deny_credit_request, Order @order = Order.find(params[:id]) @customer = @order.customer @billing_entity = @order.billing_entity @order.deny_credit_request FinancialsMailer.credit_request_denied_notification(@customer, @order.balance, @order).deliver_later flash[:info] = 'Credit request denied and rep notified.' redirect_to_return_path_or_default @order end |
#destroy ⇒ Object
DELETE /orders/1
780 781 782 783 784 785 786 787 788 789 790 791 |
# File 'app/controllers/orders_controller.rb', line 780 def destroy parent_customer = @order.customer if @order.ok_to_delete?(current_account) @order.destroy flash[:info] = 'Order has been deleted' redirect_to customer_path(parent_customer) else flash[:error] = @order.errors_with_deliveries_errors.join(',') redirect_to order_url(@order) end end |
#disable_auto_coupon ⇒ void
This method returns an undefined value.
Disables auto-coupons on the order and refreshes the discount summary.
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'app/controllers/orders_controller.rb', line 198 def disable_auto_coupon @order = Order.find(params[:id]) @order.update_attribute!(:disable_auto_coupon, true) flash[:info] = 'Auto coupons are now disabled, if any auto coupons were applied you can delete them and they will not come back.' respond_to do |format| format.turbo_stream do @order.reload @discounts = @order.discounts.includes(:coupon) render turbo_stream: turbo_stream.replace( 'discount_summary', partial: 'discounts/summary', locals: { itemizable: @order } ) end format.html do redirect_to_return_path_or_default(order_discounts_path(@order)) end end end |
#do_move ⇒ void
This method returns an undefined value.
Moves the order to another customer/opportunity via Order::Mover.
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 |
# File 'app/controllers/orders_controller.rb', line 1381 def do_move @order = Order.find(params[:id]) (:edit, @order) customer = Customer.find(params.dig(:move, :customer_id)) if params.dig(:move, :customer_id).present? opportunity = customer.opportunities.find(params.dig(:move, :opportunity_id)) if params.dig(:move, :opportunity_id).present? res = Order::Mover.new(@order).move_to(customer:, opportunity:) if res.success? redirect_to order_path(@order) else flash.now[:error] = res.errors.to_sentence.capitalize render :move, status: :unprocessable_content end end |
#edi_force_price_match ⇒ void
This method returns an undefined value.
Forces the order's prices to match its EDI pricing, refreshing the
line-items grid and discount summary.
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 |
# File 'app/controllers/orders_controller.rb', line 1356 def edi_force_price_match errs = [] if @order.edi_price_matcheable? (:edi_force_price_match, @order) errs = @order.edi_force_price_match else errs << 'Order is not an EDI order or already matches the EDI pricing' end flash.now[:error] = errs.join('. ') if errs.any? respond_to do |format| format.turbo_stream { render turbo_stream: itemizable_recalculate_streams(@order) } format.html { redirect_to_return_path_or_default order_url(@order) } end end |
#edit ⇒ Object
GET /customers/1/orders/1/edit
121 |
# File 'app/controllers/orders_controller.rb', line 121 def edit; end |
#edit_sales_support_rep ⇒ void
This method returns an undefined value.
Renders the sales-support-rep editor.
795 796 797 798 |
# File 'app/controllers/orders_controller.rb', line 795 def edit_sales_support_rep (:edit_sales_support_rep, @order) @employees = Employee.active.order(:full_name) end |
#enable_auto_coupon ⇒ void
This method returns an undefined value.
Re-enables auto-coupons on the order, recalculates discounts, and
refreshes the discount summary.
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'app/controllers/orders_controller.rb', line 222 def enable_auto_coupon @order = Order.find(params[:id]) @order.disable_auto_coupon = false @order.save # Recalculate discounts after auto coupons are applied @order.reload.reset_discount flash[:info] = 'Auto coupons are enabled, if any auto coupons qualified they have been added automatically.' respond_to do |format| format.turbo_stream do @order.reload @discounts = @order.discounts.includes(:coupon) render turbo_stream: turbo_stream.replace( 'discount_summary', partial: 'discounts/summary', locals: { itemizable: @order } ) end format.html do redirect_to_return_path_or_default(order_discounts_path(@order)) end end end |
#enter_rooms ⇒ void
This method returns an undefined value.
Enqueues the worker that enters the selected room configurations onto the
order, redirecting to the job page.
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 |
# File 'app/controllers/orders_controller.rb', line 835 def enter_rooms params[:order] ||= {} params[:order][:room_configuration_ids] ||= [] new_rc_ids = (params[:order][:room_configuration_ids] || []).uniq.sort = { order_id: @order.id, room_configuration_ids: new_rc_ids, redirect_path: order_path(@order, tab: 'rooms') }.stringify_keys job_id = EnterOrderRoomsWorker.perform_async() if job_id.blank? && (job_id = BackgroundJobStatus.search(worker_klass: 'EnterOrderRoomsWorker', args: ).first&.dig(:job_id)) flash[:warning] = 'A similar job was already enqueued, watching status of that job now' end if job_id.present? redirect_to job_path(job_id) else flash[:warning] = 'There was a problem queuing the job' redirect_to order_path(@order, tab: 'rooms') end end |
#exclude_from_payment_check ⇒ void
This method returns an undefined value.
Excludes the order from the payment check.
180 181 182 |
# File 'app/controllers/orders_controller.rb', line 180 def exclude_from_payment_check @order.update(exclude_from_payment_check: true) end |
#fix_catalog ⇒ void
This method returns an undefined value.
Re-maps the order's catalog items after a catalog change and flashes the
per-item results.
284 285 286 287 288 |
# File 'app/controllers/orders_controller.rb', line 284 def fix_catalog @order = Order.find(params[:id]) flash[:info] = @order.fix_catalog.join('<br>') redirect_to_return_path_or_default order_path(@order) end |
#force_invoiced_status ⇒ void
This method returns an undefined value.
Forces the order to invoiced status (admin escape hatch for orders stuck
in pending payment after all deliveries invoiced).
455 456 457 458 459 460 461 |
# File 'app/controllers/orders_controller.rb', line 455 def force_invoiced_status # Method created for admins to force an order to be Invoiced. Usefull for when the order remains in pending payment # after all deliveries have been invoiced, due to an error in coupons or shipping. Oscar says it's better to inform # accounting to take care of the mismatch than to leave the order in pending_payment @order.trigger_invoiced! redirect_to order_url(@order) end |
#get_details ⇒ void
This method returns an undefined value.
Returns order details (room ids, goods line items, product lines) as JSON.
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 |
# File 'app/controllers/orders_controller.rb', line 1001 def get_details id = params[:order_id] if id.blank? render json: { error: 'not-found' }.to_json, status: :not_found else order = Order.find(id) lines = LineItem.where(resource_type: 'Order', resource_id: order.id).goods product_lines = [] line_collection = [] lines.each do |l| line_collection << { id: l.item.id, sku: l.item.sku, quantity: l.quantity } product_lines << l.item.primary_product_line.id unless l.item.primary_product_line.nil? end render json: { room_ids: order.room_configuration_ids.join(','), items: line_collection, product_lines: product_lines.uniq } end end |
#get_spiff_enrollments ⇒ void
This method returns an undefined value.
Loads the selected contact's active spiff enrollment for the spiff form.
918 919 920 921 922 923 924 925 926 |
# File 'app/controllers/orders_controller.rb', line 918 def get_spiff_enrollments @contact = @customer.contacts.find_by(id: params[:order_spiff_rep_id]) if @contact && @contact.active_spiff_enrollment.present? && @contact.active_spiff_enrollment.is_active? @spiff_enrollments = [@contact.active_spiff_enrollment] @order.spiff_enrollment = @contact.active_spiff_enrollment else @spiff_enrollments = [] end end |
#include_in_payment_check ⇒ void
This method returns an undefined value.
Re-includes the order in the payment check.
186 187 188 |
# File 'app/controllers/orders_controller.rb', line 186 def include_in_payment_check @order.update(exclude_from_payment_check: false) end |
#index ⇒ Object
GET /customers/1/orders
29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'app/controllers/orders_controller.rb', line 29 def index if context_object build_orders_tab_data(context_object) else @context_object = nil @q = Order.none.ransack(params[:q]) @q.sorts = 'created_at DESC' if @q.sorts.blank? @pagy, @orders = pagy(:countish, @q.result) end respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#lookup ⇒ void
This method returns an undefined value.
Order autocomplete/search endpoint (JSON for TomSelect, HTML partial for
lookup suggestions), honoring state, customer, and wildcard filters.
931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 |
# File 'app/controllers/orders_controller.rb', line 931 def lookup q = params[:q].try(:upcase)&.split&.first order_id = params[:order_id].presence customer_id = params[:customer_id].presence state_in = params[:state_in].presence if order_id order = Order.find(order_id) respond_to do |format| format.json { render json: { results: { id: order_id, text: "[#{order.reference_number}] #{order.customer.full_name} (#{order.shipped_date.to_fs(:crm_default)})" } } } format.html do @results = [order] render partial: 'orders/lookup_suggestions', locals: { results: @results } end end else @results = Order.all @results = @results.where(state: state_in) if state_in if customer_id # You can search outside the customer's order scope if this flag is specified if params[:allow_open_order_link].to_b && q.present? # if a customer id was specified, we will still limit to orders in the same company id as the original customer company_id = Customer.joins(:catalog).where(id: customer_id).pick('catalogs.company_id') @results = @results.joins(customer: :catalog).where(Catalog[:company_id].eq(company_id)) else @results = @results.where(customer_id:) end end if q.present? @results = if params[:with_wildcard].to_b @results.like_lookup(q) else @results.lookup(q) end end json_result = TomSelect.format_json_results(self, @results, params[:page].presence, params[:per_page].presence) do |e| { id: e.id, text: e.selection_name, label: e.selection_name, reference: e.reference_number, order_link: order_path(e), state: e.state, shipped: e.shipped_date.present? ? e.shipped_date.to_fs(:crm_default) : 'not shipped', opportunity: e.opportunity&.name, customer: e.customer.full_name, customer_link: customer_path(e.customer), contact_id: e.contact_id, contact_full_name: e.contact&.full_name } end respond_to do |format| format.json { render json: json_result } format.html { render partial: 'orders/lookup_suggestions', locals: { results: @results.limit(20) } } end end end |
#lookup_row ⇒ Object
Return a server-rendered order row for the support case orders table
989 990 991 992 993 994 995 996 997 |
# File 'app/controllers/orders_controller.rb', line 989 def lookup_row o = Order.find_by(id: params[:id]) if o.nil? render html: ''.html_safe, status: :not_found else # Reuse the shared row partial to guarantee consistent markup render partial: 'support_cases/orders_table_row', locals: { o: o, hide_checkbox: false } end end |
#move ⇒ void
This method returns an undefined value.
Renders the move-order form.
1374 1375 1376 1377 |
# File 'app/controllers/orders_controller.rb', line 1374 def move @order = Order.find(params[:id]) (:edit, @order) end |
#new ⇒ Object
GET /customers/1/orders/new
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'app/controllers/orders_controller.rb', line 84 def new @support_case = SupportCase.find(params[:support_case_id]) if params[:support_case_id] @opportunity = Opportunity.find(params[:opportunity_id]) if params[:opportunity_id] @room_configuration = RoomConfiguration.find(params[:room_configuration_id]) if params[:room_configuration_id] @opportunity ||= @room_configuration&.opportunity @contact = Contact.find(params[:contact_id]) if params[:contact_id] @customer = Customer.find(params[:customer_id]) if params[:customer_id] @customer ||= @opportunity&.customer @customer ||= @contact&.customer @customer ||= @support_case&.customer @order = @customer.orders.build( customer: @customer, opportunity: @opportunity, contact: @contact, recalculate_shipping: false, do_not_detect_shipping: true, source: Order.default_source_for(customer: @customer, opportunity: @opportunity) ) @order.order_type = "#{@opportunity.opportunity_type}O" if @opportunity @order.order_type = params[:order_type] if params[:order_type] @order.support_case_ref = @support_case.case_number if @support_case @order.tracking_email << @order.primary_party&.email if @support_case && @order.primary_party&.email.present? (:create, @order) # Enabling this code would populate the channel notification emails if we decided to make billing_emails the ulimate authority for where invoices get sent # @order.billing_emails = @order.default_billing_emails @order.single_origin = true if @customer.try(:is_direct_buy?) # patch for now for Direct Buy, must be single origin if @order.save redirect_to_return_path_or_default account_managers_order_path(@order) else flash[:error] = "Could not create order. #{@order.errors_with_deliveries_errors.join(', ')}" redirect_to_return_path_or_default customer_url(@customer) end end |
#pick_serial_numbers ⇒ void
This method returns an undefined value.
Renders the serial-number picking screen, auto-reserving serial numbers
first.
1029 1030 1031 1032 1033 |
# File 'app/controllers/orders_controller.rb', line 1029 def pick_serial_numbers @order = Order.find(params[:id]) @order.auto_reserve_serial_numbers load_line_items_requiring_reservation end |
#place_cr_hold ⇒ void
This method returns an undefined value.
Puts the order on CR hold under an advisory lock, optionally routing to
stock reservation when reserve_stock is set.
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 |
# File 'app/controllers/orders_controller.rb', line 652 def place_cr_hold res = Order.with_advisory_lock_result("order_#{@order.id}", timeout_seconds: 120) do @order.reload if @order.can_cr_hold?(current_user) if @order.has_early_purchased_label? && @order.early_label_purchased_recently? minutes_since = ((Time.current - @order.early_label_purchased_at) / 60).round(1) wait_minutes = (Order::EARLY_LABEL_RAPID_VOID_THRESHOLD_MINUTES - minutes_since).ceil flash[:warning] = "Early label was purchased #{minutes_since} minutes ago. Please wait #{wait_minutes} more minute(s) before holding/canceling, or void the label manually first." else @order.cr_hold! if @order.in_cr_hold? @order.update(is_manual_hold: true) else flash[:error] = "Order cannot be put into CR hold. #{@order.errors_with_deliveries_errors.to_sentence.capitalize} #{@order.shipping_address.errors_to_s}." end end end end flash[:error] = "Could not acquire lock on order #{@order}, try again later" unless res.lock_was_acquired? if @order.in_cr_hold? && params[:reserve_stock].to_b redirect_to pick_lines_inventory_commits_path(resource_type: 'Order', resource_id: @order.id), notice: 'Order is on hold, please select which items you would like to reserve and click Save' else redirect_to_return_path_or_default order_url(@order) end end |
#process_spiff ⇒ void
This method returns an undefined value.
Marks the order's spiff as paid (accounting reps only).
72 73 74 75 76 77 78 79 80 81 |
# File 'app/controllers/orders_controller.rb', line 72 def process_spiff access_denied && return unless current_account&.has_role?('accounting_rep') if @order.spiff_paid flash[:info] = 'Order spiff status updated successfully' else flash[:error] = 'Unable to update order spiff status' end redirect_to_return_path_or_default order_path(@order) end |
#profit_margins ⇒ void
This method returns an undefined value.
Renders the profit-margins editor.
1020 1021 1022 1023 1024 |
# File 'app/controllers/orders_controller.rb', line 1020 def profit_margins @order = Order.find(params[:id]) :manage_profit_margins, @order render layout: 'crm/crm' end |
#recalculate_discount ⇒ void
This method returns an undefined value.
Recalculates the order's discounts and refreshes the line-items grid and
discount summary.
863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 |
# File 'app/controllers/orders_controller.rb', line 863 def recalculate_discount @order = @customer.orders.find(params[:id]) @order.reset_discount if @order.errors_with_deliveries_errors.any? flash.now[:error] = "Problem while recalculating discount: #{@order.errors_with_deliveries_errors.join(', ')}" else flash.now[:success] = 'Discount recalculated.' end respond_to do |format| format.turbo_stream { render turbo_stream: itemizable_recalculate_streams(@order) } format.html do redirect_to_return_path_or_default order_url(@order) end end end |
#recalculate_taxes ⇒ void
This method returns an undefined value.
Refreshes the order's tax rate (disabled for CI-invoice credit orders) and
refreshes the line-items grid and discount summary.
883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 |
# File 'app/controllers/orders_controller.rb', line 883 def recalculate_taxes if @order.ci_invoice_credit_order? flash.now[:warning] = 'Tax recalculation is disabled for credit orders from CI invoices. Taxes are inherited from the original invoice.' else @order.refresh_tax_rate if @order.errors.any? flash.now[:error] = "Problem while recalculating taxes: #{@order.errors..join(', ')}" else flash.now[:success] = 'Taxes recalculated.' end end respond_to do |format| format.turbo_stream { render turbo_stream: itemizable_recalculate_streams(@order) } format.html do redirect_to_return_path_or_default order_url(@order) end end end |
#release_back_order ⇒ void
This method returns an undefined value.
Releases a back-ordered order, detouring to serial-number reservation when
required.
637 638 639 640 641 642 643 644 645 646 647 |
# File 'app/controllers/orders_controller.rb', line 637 def release_back_order old_state = @order.state @order.release_order if @order.state == old_state flash[:info] = "Order can't be released. #{@order.errors_with_deliveries_errors.to_sentence.capitalize} #{@order.shipping_address.errors_to_s}." elsif @order.needs_serial_number_reservation? flash[:info] = 'Order released, but requires serial number reservations. Please complete the reservations and save' redirect_to(pick_serial_numbers_order_path(@order)) && return end redirect_to @order end |
#release_cr_hold ⇒ void
This method returns an undefined value.
Releases the order from CR hold under an advisory lock.
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 |
# File 'app/controllers/orders_controller.rb', line 680 def release_cr_hold early_label_result = nil res = Order.with_advisory_lock_result("order_#{@order.id}", timeout_seconds: 120) do # Reload because we want to make sure the order is still in the right state @order.reload if @order.can_release_order? @order.update(is_manual_hold: false) @order.release_order if @order.in_cr_hold? flash[:error] = "Order cannot be released from CR hold. #{@order.hold_order_reasons&.join('. ')} #{@order.errors_with_deliveries_errors.to_sentence.capitalize} #{@order&.shipping_address&.errors&.&.join('. ')}." else # Capture early label result for flash message early_label_result = @order. end end end flash[:error] = "Could not acquire lock on order #{@order}, try again later" unless res.lock_was_acquired? # Display early label purchase result flash[early_label_result[:type]] = early_label_result[:message] if early_label_result.present? redirect_to_return_path_or_default order_url(@order) end |
#release_management_hold ⇒ void
This method returns an undefined value.
Releases the order from management hold.
765 766 767 768 769 |
# File 'app/controllers/orders_controller.rb', line 765 def release_management_hold (:release_management_hold, @order) @order.release_management_hold! if @order.in_management_hold? redirect_to_return_path_or_default order_url(@order) end |
#resend_google_offline_conversion ⇒ void
This method returns an undefined value.
Re-sends the Google Ads offline conversion for the order and flashes the
result details.
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 |
# File 'app/controllers/orders_controller.rb', line 723 def resend_google_offline_conversion res = Invoicing::GoogleConversionReporter.new.send_new_order_conversion(@order) = res[:meta] || {} # Include reason/status/error to aid debugging when meta is empty summary_rows = [] summary_rows << ['status', ['result'] || res[:status] || res[:success]] summary_rows << ['reason', res[:reason]] if res[:reason] summary_rows << ['error', ['error'] || res[:error]] if (['error'] || res[:error]).present? = (.to_a + summary_rows).map { |key, value| "<strong>#{key}:</strong> #{value}" }.join('<br>') rb_debug_link = "<a href='https://appsignal.com/warmlyyours/sites/heatwave-production/errors?search=google' target='_blank'>Debug</a>" if res[:success] flash[:info] = "Success:<br>#{}<br>" + rb_debug_link else flash[:error] = "Failed: #{res[:reason] || 'unknown'}<br>#{}<br>" + rb_debug_link end redirect_to_return_path_or_default order_url(@order) end |
#resend_pinterest_conversion ⇒ void
This method returns an undefined value.
Re-sends the Pinterest conversion for the order and flashes the result
details.
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 |
# File 'app/controllers/orders_controller.rb', line 745 def resend_pinterest_conversion res = Pinterest::ConversionReporter.new.send_order_conversion(@order) = res[:meta] || {} summary_rows = [] summary_rows << ['status', [:result] || ['result'] || res[:status] || res[:success]] summary_rows << ['reason', res[:reason]] if res[:reason] summary_rows << ['error', [:error] || ['error'] || res[:error]] if ([:error] || ['error'] || res[:error]).present? = (.to_a + summary_rows).map { |key, value| "<strong>#{key}:</strong> #{value}" }.join('<br>') debug_link = "<a href='https://appsignal.com/warmlyyours/sites/heatwave-production/errors?search=pinterest' target='_blank'>Debug</a>" if res[:success] flash[:info] = "Pinterest conversion sent:<br>#{}<br>#{debug_link}".html_safe else flash[:error] = "Pinterest conversion failed: #{res[:reason] || 'unknown'}<br>#{}<br>#{debug_link}".html_safe end redirect_to_return_path_or_default order_url(@order) end |
#resend_review_request ⇒ void
This method returns an undefined value.
Re-queues the Reviews.io invitation for the order.
707 708 709 710 711 712 713 714 715 716 717 718 |
# File 'app/controllers/orders_controller.rb', line 707 def resend_review_request result = Api::ReviewsIo::InvitationSender.new(order: @order).process case result when Api::ReviewsIo::InvitationSender::RESULT_SUCCESS flash[:info] = 'Reviews.io invitation queued successfully.' when Api::ReviewsIo::InvitationSender::RESULT_SKIPPED flash[:warning] = 'Reviews.io invitation skipped (order may not be eligible or missing customer email).' else flash[:error] = 'Reviews.io invitation failed. Check logs for details.' end redirect_to_return_path_or_default order_url(@order, tab: 'reviews') end |
#restore ⇒ void
This method returns an undefined value.
Restores a cancelled order.
172 173 174 175 176 |
# File 'app/controllers/orders_controller.rb', line 172 def restore @order.restore flash[:error] = @order.errors_with_deliveries_errors.join(', ') if @order.errors_with_deliveries_errors.any? redirect_to_return_path_or_default order_path(@order) end |
#review_credit_request ⇒ void
This method returns an undefined value.
Renders the credit-request review screen, redirecting away when the
request was already processed.
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 |
# File 'app/controllers/orders_controller.rb', line 1279 def review_credit_request :review_credit_request, Order @order = Order.find(params[:id]) @customer = @order.customer @billing_entity = @order.billing_entity return unless !@order.credit_request_pending? || @order.editing_locked? if @order.credit_request_approved? notice = 'Credit request has already been approved.' elsif @order.credit_request_denied? notice = 'Credit request has already been denied.' elsif @order.credit_request_cancelled? notice = 'Credit request has already been cancelled.' elsif @order.no_credit_requested? notice = 'No credit has been requested for this order.' elsif @order.editing_locked? notice = 'Order has already been processed.' end redirect_to(@order, notice:) end |
#review_echeck_request ⇒ void
This method returns an undefined value.
Renders the e-check authorization review screen, redirecting away when the
order was already processed.
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 |
# File 'app/controllers/orders_controller.rb', line 1329 def review_echeck_request :review_echeck_request, Order @order = Order.find(params[:id]) @customer = @order.customer @billing_entity = @order.billing_entity @echeck_payment = @order..sum(&:amount) return unless !@order. || @order.editing_locked? redirect_to(@order, notice: 'Order has already been processed.') end |
#rooms ⇒ void
This method returns an undefined value.
Renders the rooms step, preloading all room configurations available to
the order and its opportunity.
821 822 823 824 825 826 827 828 829 830 |
# File 'app/controllers/orders_controller.rb', line 821 def rooms # Load all available room configurations (client-side filtering via Stimulus) # Get all available room configurations from order and opportunity available_rc_ids = (@order.room_configuration_ids + (@order.opportunity&.room_configuration_ids || [])).uniq # Use preload to avoid N+1 queries - loads associations in separate queries @room_configurations = RoomConfiguration.where(id: available_rc_ids) .order('room_configurations.updated_at DESC, room_configurations.name') .preload(:room_layout_images, :controlled_rooms, :controlled_by) end |
#send_public_payment_link ⇒ void
This method returns an undefined value.
Starts a new ORDER_PAYMENT communication (public payment link) for the
order, pre-addressed to the given email.
1343 1344 1345 1346 1347 1348 1349 1350 1351 |
# File 'app/controllers/orders_controller.rb', line 1343 def send_public_payment_link email = params[:communication][:email] @order = Order.find(params[:id]) comm = CommunicationBuilder.new(resource: @order, template_system_code: 'ORDER_PAYMENT').to_params comm = comm.merge(emails: email) unless email.nil? redirect_to new_communication_path(comm) end |
#send_tracking_email ⇒ void
This method returns an undefined value.
Sends the tracking (or ready-for-pickup) email for the order.
905 906 907 908 909 910 911 912 913 914 |
# File 'app/controllers/orders_controller.rb', line 905 def send_tracking_email order = Order.find(params[:id]) result = if order.is_warehouse_pickup? order.send_ready_for_pickup_email else order.send_tracking_email end flash[:info] = result[:status_message] if result[:status_message].present? redirect_to_return_path_or_default order_url(order) end |
#service ⇒ void
This method returns an undefined value.
Renders the service-scheduling step for orders containing schedulable
services.
382 383 384 385 386 387 388 389 390 391 392 |
# File 'app/controllers/orders_controller.rb', line 382 def service if @order.includes_schedulable_service? @support_case = @order.smartservice_ticket @support_case ||= SupportCase.new(case_type: 'SmartService') @addresses = @customer.addresses.order(:company_name_override, :person_name_override, :state_code, :street1) @new_address = @customer.addresses.new else flash[:error] = 'This order does not contain any schedulable services.' redirect_to_return_path_or_default(order_url(@order)) end end |
#set_shipping_address ⇒ void
This method returns an undefined value.
Saves the shipping-address selection (address-book pick, one-time-address
update, or new address) and proceeds to item picking.
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
# File 'app/controllers/orders_controller.rb', line 307 def set_shipping_address set_new_address @block_address_edit = @order.editing_locked? || (@order. && !@context_user.manager?) if @block_address_edit flash.now[:error] = 'Shipping address cannot be updated because the order has pending authorized pre-payments. Void the payment first and re-authorize payment afterwards.' render :shipping_address, status: :unprocessable_content else # Intercept address id address_id = params[:order]&.delete(:shipping_address_id) @order.attributes = params[:order] if params[:order].present? validate_new_address = false if address_id.to_i > 0 # Address book pick @order.shipping_address_id = address_id.to_i elsif @order.shipping_address&.one_time_only # update the one time address @order.shipping_address.attributes = params[:address] @new_address = @order.shipping_address @new_address&.save validate_new_address = true elsif params[:address].present? params[:address].delete(:party_id) unless params[:address][:party_id] && (params[:address][:party_id].to_i > 0) @new_address = Address.create(params[:address]) @order.shipping_address = @new_address validate_new_address = true end if ((validate_new_address && @new_address.errors.blank?) || !validate_new_address) && @order.save save_shipping_as_billing_address if params[:save_as_billing_address] == '1' && @customer.billing_address.nil? if @order.ships_freight_but_address_not_freight_ready? check_freight_fields_and_redirect else result = @order.last_shipping_rate_request_result handle_shipping_flash_messaging(result) next_step_url = pick_items_path(order_id: @order.id, return_path: shipping_order_path(@order)) if @customer.addresses.count <= 1 && !@new_address&.new_record? && @new_address.country_iso3 && (@new_address.country_iso3 != @customer.catalog.country_iso3) && (cat = Store.find_by(country_iso3: @new_address.country_iso3)&.primary_catalog) flash[:error] = "Customer's first address country of #{@new_address.country.printable_name} does not match customer's existing catalog country of #{@customer.catalog.country.printable_name}!" redirect_to edit_catalog_customer_path(@customer, new_catalog_id: cat.id, return_path: @return_path || next_step_url) else redirect_to_return_path_or_default next_step_url end end else flash.now[:error] = @order.errors_to_s.presence || 'Could not update shipping address.' render :shipping_address, status: :unprocessable_content end end end |
#setup_service ⇒ void
This method returns an undefined value.
Creates or links the SmartService support case for the order's schedulable
services and advances the order to pending payment.
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 |
# File 'app/controllers/orders_controller.rb', line 397 def setup_service = params[:service_creation_option] existing_ticket = params[:existing_support_case] unless == 'skip_support_case' if == 'existing_support_case' sc = SupportCase.find(existing_ticket) sc.update(params[:support_case].except(:service_address_id)) sc.convert_to_stk sc.room_configuration_ids = @order.room_configuration_ids if @order.room_configuration_ids.any? sc.order_ids = [@order.id] elsif == 'new_support_case' sc = SupportCase.new(params[:support_case]) sc.case_type = 'SmartService' sc.send(:set_case_number) sc.state = 'pending_service_payment' sc.priority = 'Low' sc.build_participants_and_rooms(order_id: @order.id) end if !@order.is_remote_service? && (params[:support_case][:service_address_id].to_i == 0) address = @customer.addresses.new(params[:address]) address.save sc.service_address_id = address.id end service = @order.line_items.smartservice_items.map { |a| a.item.name }.join('; ') descript = '<p>Customer requested: </p>' service.split(';').each do |ser| descript += "<li>#{ser}</li>" end descript += "<br><p>Preferred time frame is <b>#{sc.preferred_service_timeframe}</b></p>" sc.description = descript sc.service = service end if == 'skip_support_case' || sc.try(:save) @order.pending_payment if @order.awaiting_deliveries? # already had payment so it went straight to warehouse # Check for early label purchase result early_label_result = @order. flash[early_label_result[:type]] = early_label_result[:message] if early_label_result.present? redirect_to_return_path_or_default(order_url(@order)) elsif @order.profit_review? flash[:warning] = 'Order profit not met' redirect_to_return_path_or_default(order_url(@order)) else redirect_to_return_path_or_default(order_discounts_url(@order)) end else flash.now[:error] = sc&.errors&.&.to_sentence.presence || 'Could not save support case for service order.' render :service, status: :unprocessable_content end end |
#ship_confirm_service_deliveries ⇒ void
This method returns an undefined value.
Ship-confirms all service deliveries on the order that are ready to
fulfill.
774 775 776 777 |
# File 'app/controllers/orders_controller.rb', line 774 def ship_confirm_service_deliveries @order.deliveries.select(&:service_ready_to_fulfill?).each(&:individual_auto_ship_confirm) redirect_to_return_path_or_default order_path(@order) end |
#shipping ⇒ void
This method returns an undefined value.
Renders the shipping step, defaulting label instructions, phone, and
tracking email; requires a shipping address first.
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 |
# File 'app/controllers/orders_controller.rb', line 362 def shipping @ship_quotable = @order if @order.shipping_address @order.label_instructions ||= @order.po_number.to_s phone_party = @order.contact || @order.customer @order.shipping_phone ||= phone_party.try(:phone) || phone_party.try(:cell_phone) @order.set_default_tracking_email if params[:shipping_updated] result = eval(@order.last_shipping_rate_request_result.to_s) # rubocop:disable Security/Eval handle_shipping_flash_messaging(result, params[:shipping_update_type]) end else flash[:error] = 'Please specify an address before looking at shipping costs.' redirect_to_return_path_or_default shipping_address_order_path(@order) end end |
#shipping_address ⇒ void
This method returns an undefined value.
Renders the shipping-address step, defaulting the address and phone from
the customer/contact and locking edits when payments are authorized.
293 294 295 296 297 298 299 300 301 302 |
# File 'app/controllers/orders_controller.rb', line 293 def shipping_address @order.shipping_address_id = @order.customer.try(:shipping_address_id) || @order.customer.addresses.first.try(:id) if @order.shipping_address_id.nil? set_new_address if @order.shipping_phone.blank? party = @order.contact || @order.customer @order.shipping_phone = party.phone || party.cell_phone @order.shipping_phone ||= @order.customer.phone || @order.customer.cell_phone end @block_address_edit = @order.editing_locked? || (@order. && !@context_user.manager?) end |
#show ⇒ Object
GET /customers/1/orders/1
Accepts ID or reference_number (e.g., SO123456)
46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'app/controllers/orders_controller.rb', line 46 def show if params[:shipping_updated] result = eval(@order.last_shipping_rate_request_result.to_s) # rubocop:disable Security/Eval handle_shipping_flash_messaging(result, params[:shipping_update_type]) end # Reviews.io data is loaded lazily when reviews tab is viewed (see tab_reviews) respond_to do |format| format.html do # material_alerts @flag = @order.shipping_address.try(:country).try(:iso).try(:downcase) end end end |
#split ⇒ void
This method returns an undefined value.
Renders the split-order form.
599 |
# File 'app/controllers/orders_controller.rb', line 599 def split; end |
#split_back_order_all ⇒ void
This method returns an undefined value.
Moves the entire order to back order.
627 628 629 630 631 632 |
# File 'app/controllers/orders_controller.rb', line 627 def split_back_order_all Order.transaction do @order.back_order! end redirect_to(order_url(@order)) end |
#split_selected ⇒ void
This method returns an undefined value.
Splits the selected line items into a back order via Order::Splitter.
603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 |
# File 'app/controllers/orders_controller.rb', line 603 def split_selected order_splitter = Order::Splitter.new(@order) order_splitter.split_selected(params[:line_items], params[:txid]) case order_splitter.last_status when :ok new_order = order_splitter.new_order flash[:info] = "Order has been split and partly back ordered. Split Back Order: <a href = '#{order_url(new_order)}'>#{new_order.reference_number}</a> (current status: #{new_order.state}). <br/>Please confirm shipping option for current order, then release from CR Hold." if @order.service_only_order? redirect_to order_discounts_url(@order) else redirect_to shipping_order_url(@order) end when :invalid, :error @order.errors.add(:base, order_splitter.) render :split, status: :unprocessable_content else flash[:error] = 'Unknown return status for split action' redirect_to order_path(@order) end end |
#tab_activities ⇒ void
This method returns an undefined value.
Renders the activities tab fragment for the order.
1150 1151 1152 1153 1154 1155 1156 1157 |
# File 'app/controllers/orders_controller.rb', line 1150 def tab_activities (:read, @order) build_activities_tab_data(@order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_attachments ⇒ void
This method returns an undefined value.
Renders the attachments tab fragment for the order.
1117 1118 1119 1120 1121 1122 1123 1124 |
# File 'app/controllers/orders_controller.rb', line 1117 def (:read, @order) build_uploads_tab_data(@order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_communications ⇒ void
This method returns an undefined value.
Renders the communications tab fragment for the order.
1128 1129 1130 1131 1132 1133 1134 1135 |
# File 'app/controllers/orders_controller.rb', line 1128 def tab_communications (:read, @order) build_communications_tab_data(@order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_contacts ⇒ void
This method returns an undefined value.
Renders the contacts tab fragment for the order.
1083 1084 1085 1086 1087 1088 1089 |
# File 'app/controllers/orders_controller.rb', line 1083 def tab_contacts (:read, @order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_credit_memos ⇒ void
This method returns an undefined value.
Renders the credit-memos tab fragment for the order.
1237 1238 1239 1240 1241 1242 1243 |
# File 'app/controllers/orders_controller.rb', line 1237 def tab_credit_memos (:read, @order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_edi_documents ⇒ void
This method returns an undefined value.
Renders the EDI documents tab fragment, loading the order's EDI
communication logs.
1203 1204 1205 1206 1207 1208 1209 1210 |
# File 'app/controllers/orders_controller.rb', line 1203 def tab_edi_documents (:read, @order) @edi_communication_logs = @order.edi_communication_logs.order(created_at: :desc) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_inventory ⇒ void
This method returns an undefined value.
Renders the inventory tab fragment: remaining-to-ship item groups.
1181 1182 1183 1184 1185 1186 1187 1188 |
# File 'app/controllers/orders_controller.rb', line 1181 def tab_inventory (:read, @order) @item_groups = Inventory::OrderedRemainingItems.new.process(@order, nest_kit_components: true).item_groups respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_invoices ⇒ void
This method returns an undefined value.
Renders the invoices tab fragment for the order.
1192 1193 1194 1195 1196 1197 1198 |
# File 'app/controllers/orders_controller.rb', line 1192 def tab_invoices (:read, @order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_line_items ⇒ void
This method returns an undefined value.
Renders the line-items tab fragment for the order.
1063 1064 1065 1066 1067 1068 1069 |
# File 'app/controllers/orders_controller.rb', line 1063 def tab_line_items (:read, @order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_main ⇒ void
This method returns an undefined value.
Renders the main tab fragment for the order.
1073 1074 1075 1076 1077 1078 1079 |
# File 'app/controllers/orders_controller.rb', line 1073 def tab_main (:read, @order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_marketing ⇒ void
This method returns an undefined value.
Renders the marketing tab fragment for the order.
1259 1260 1261 1262 1263 1264 1265 |
# File 'app/controllers/orders_controller.rb', line 1259 def tab_marketing (:read, @order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_material_alerts ⇒ void
This method returns an undefined value.
Renders the material-alerts tab fragment for the order.
62 63 64 65 66 67 68 |
# File 'app/controllers/orders_controller.rb', line 62 def tab_material_alerts @material_alerts = @order.get_material_alerts if @order && @order.id.present? respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_payments ⇒ void
This method returns an undefined value.
Renders the payments tab fragment for the order.
1161 1162 1163 1164 1165 1166 1167 |
# File 'app/controllers/orders_controller.rb', line 1161 def tab_payments (:read, @order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_reviews ⇒ void
This method returns an undefined value.
Renders the reviews tab fragment, loading Reviews.io data for the order.
1247 1248 1249 1250 1251 1252 1253 1254 1255 |
# File 'app/controllers/orders_controller.rb', line 1247 def tab_reviews (:read, @order) # Fetch Reviews.io reviews for this order (only when reviews tab is viewed) prepare_order_reviews_io_data respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_rmas ⇒ void
This method returns an undefined value.
Renders the RMAs tab fragment for the order.
1227 1228 1229 1230 1231 1232 1233 |
# File 'app/controllers/orders_controller.rb', line 1227 def tab_rmas (:read, @order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_rooms ⇒ void
This method returns an undefined value.
Renders the rooms tab fragment for the order.
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 |
# File 'app/controllers/orders_controller.rb', line 1103 def tab_rooms (:read, @order) @opportunity = @order.opportunity @editing_locked = @order.editing_locked? @return_path = order_path(@order, tab: 'rooms') build_rooms_tab_data(@order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_shipping ⇒ void
This method returns an undefined value.
Renders the shipping tab fragment for the order.
1093 1094 1095 1096 1097 1098 1099 |
# File 'app/controllers/orders_controller.rb', line 1093 def tab_shipping (:read, @order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_sms ⇒ void
This method returns an undefined value.
Renders the SMS tab fragment for the order.
1139 1140 1141 1142 1143 1144 1145 1146 |
# File 'app/controllers/orders_controller.rb', line 1139 def tab_sms (:read, @order) build_sms_tab_data(@order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_tickets ⇒ void
This method returns an undefined value.
Renders the tickets tab fragment for the order.
1171 1172 1173 1174 1175 1176 1177 |
# File 'app/controllers/orders_controller.rb', line 1171 def tab_tickets (:read, @order) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#tab_warranty ⇒ void
This method returns an undefined value.
Renders the warranty tab fragment, loading the order's warranties.
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 |
# File 'app/controllers/orders_controller.rb', line 1214 def tab_warranty (:read, @order) @warranties = @order.warranties .includes(:customer, :created_by, :products, :uploads) .order(submitted_at: :desc) respond_to do |format| format.html { render layout: should_render_layout? } format.turbo_stream end end |
#update ⇒ Object
PUT /customers/1/orders/1
138 139 140 141 142 143 144 |
# File 'app/controllers/orders_controller.rb', line 138 def update if @order.update(params[:order]) redirect_to_return_path_or_default order_url(@order) else render action: :edit, status: :unprocessable_content end end |
#update_profit_margins ⇒ void
This method returns an undefined value.
Saves the order's minimum profit markup, attempting release from profit
review when margins now pass.
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 |
# File 'app/controllers/orders_controller.rb', line 496 def update_profit_margins (:manage_profit_margins, @order) if order_profit_margins_params.to_hash['min_profit_markup'].present? if @order.update(order_profit_margins_params) if @order.can_release_from_profit_review? flash[:info] = 'Order released from profit review' @order.release_from_profit_review # Try to release elsif @order.profit_review? flash[:error] = 'Minimum profit margins not met to allow release from profit review' end redirect_to_return_path_or_default order_path(@order) else flash.now[:error] = @order.errors_to_s.presence || 'Could not update profit margins.' render :profit_margins, status: :unprocessable_content end else flash.now[:error] = 'Minimum profit margins cannot be empty' render :profit_margins, status: :unprocessable_content end end |
#update_sales_support_rep ⇒ void
This method returns an undefined value.
Saves the sales support rep and commission date.
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 |
# File 'app/controllers/orders_controller.rb', line 802 def update_sales_support_rep (:edit_sales_support_rep, @order) if @order.update_sales_support_rep( params[:order][:sales_support_rep_id], params[:order][:sales_support_commission_date] ) flash[:info] = 'Sales support rep and commission date have been updated successfully.' redirect_to_return_path_or_default order_path(@order) else flash.now[:error] = "Unable to update sales support rep: #{@order.errors..join(', ')}" @employees = Employee.active.order(:full_name) render :edit_sales_support_rep, status: :unprocessable_content end end |