Class: ShipmentReceiptsController
- Inherits:
-
CrmController
- Object
- ActionController::Base
- ApplicationController
- CrmController
- ShipmentReceiptsController
- Includes:
- Controllers::Showable
- Defined in:
- app/controllers/shipment_receipts_controller.rb
Overview
== Schema Information
Table name: shipment_receipts
id :integer not null, primary key
purchase_order_shipment_id :integer
effective_date :date
creator_id :integer
updater_id :integer
created_at :datetime
updated_at :datetime
landed_cost :decimal(8, 2)
currency :string(255)
estimated_landed_cost :decimal(8, 2)
location :string(255)
state :string(255)
serial_number_state :string
Constant Summary
Constants included from Controllers::ReferenceFindable
Controllers::ReferenceFindable::ID_EMBEDDED_PATTERNS
Constants included from Controllers::AnalyticsEvents
Controllers::AnalyticsEvents::MAX_QUEUED_EVENTS, Controllers::AnalyticsEvents::SESSION_KEY
Constants included from Controllers::ErrorRendering
Controllers::ErrorRendering::NON_CONTENT_PATH_PREFIXES
Constants included from Www::SeoHelper
Www::SeoHelper::AWARDS, Www::SeoHelper::CA_ADDRESS, Www::SeoHelper::CA_BUSINESS_HOURS, Www::SeoHelper::CA_CONTACT_POINT, Www::SeoHelper::CA_CURRENCIES, Www::SeoHelper::CA_DESCRIPTION, Www::SeoHelper::CA_FOUNDING_DATE, Www::SeoHelper::CA_GLOBAL_LOCATION_NUMBER, Www::SeoHelper::CA_LEGAL_NAME, Www::SeoHelper::CA_LOCAL_BUSINESS, Www::SeoHelper::CA_ONLINE_STORE, Www::SeoHelper::CA_RETURN_POLICY, Www::SeoHelper::CA_SALES_DEPARTMENT, Www::SeoHelper::CA_SERVICE_AREA, Www::SeoHelper::CA_URL, Www::SeoHelper::CA_VAT_ID, Www::SeoHelper::CA_WAREHOUSE_DEPARTMENT, Www::SeoHelper::CA_WAREHOUSE_HOURS, Www::SeoHelper::COMPANY_EMAIL, Www::SeoHelper::COMPANY_LOGO, Www::SeoHelper::COMPANY_NAME, Www::SeoHelper::COMPANY_SLOGAN, Www::SeoHelper::EXPERTISE, Www::SeoHelper::FAX_NUMBER, Www::SeoHelper::GS1_COMPANY_PREFIX, Www::SeoHelper::ISO6523_CODE, Www::SeoHelper::PAYMENT_METHODS, Www::SeoHelper::PHONE_NUMBER, Www::SeoHelper::PRIMARY_NAICS, Www::SeoHelper::REFUND_TYPE, Www::SeoHelper::RETURN_FEES, Www::SeoHelper::RETURN_METHOD, Www::SeoHelper::RETURN_POLICY_CATEGORY, Www::SeoHelper::SECONDARY_NAICS, Www::SeoHelper::SOCIAL_PROFILES, Www::SeoHelper::US_ADDRESS, Www::SeoHelper::US_BUSINESS_HOURS, Www::SeoHelper::US_CONTACT_POINT, Www::SeoHelper::US_CURRENCIES, Www::SeoHelper::US_DESCRIPTION, Www::SeoHelper::US_FOUNDING_DATE, Www::SeoHelper::US_GLOBAL_LOCATION_NUMBER, Www::SeoHelper::US_IMAGE, Www::SeoHelper::US_LEGAL_NAME, Www::SeoHelper::US_LOCAL_BUSINESS, Www::SeoHelper::US_ONLINE_STORE, Www::SeoHelper::US_RETURN_POLICY, Www::SeoHelper::US_SALES_DEPARTMENT, Www::SeoHelper::US_SERVICE_AREA, Www::SeoHelper::US_TAX_ID, Www::SeoHelper::US_URL, Www::SeoHelper::US_WAREHOUSE_DEPARTMENT, Www::SeoHelper::US_WAREHOUSE_HOURS
Constants included from IconHelper
IconHelper::CUSTOM_ICON_MAP, IconHelper::CUSTOM_SVG_DIR, IconHelper::DEFAULT_FAMILY
Instance Method Summary collapse
-
#assign_serial_numbers ⇒ Object
GET /shipment_receipts/:id/assign_serial_numbers — render the serial-number entry form for items that require reservation (heating mats / cables ship with manufacturer SNs we have to record on receipt).
-
#confirm_landed_costs ⇒ Object
GET /shipment_receipts/:id/confirm_landed_costs — final confirmation step before posting.
-
#create ⇒ Object
POST /shipment_receipts — receive inbound supplier shipment.
-
#do_assign_serial_numbers ⇒ Object
POST /shipment_receipts/:id/do_assign_serial_numbers — persist the entered serial numbers and route the user back to the purchase order.
-
#edit_landed_costs ⇒ Object
GET /shipment_receipts/:id/edit_landed_costs — re-open the landed-costs form when a receipt already has costs entered.
-
#enter_landed_costs ⇒ Object
GET /shipment_receipts/:id/enter_landed_costs — render the landed-costs form for first-time entry (carrier + total cost).
-
#new ⇒ Object
GET /purchase_order_shipments/:purchase_order_shipment_id/shipment_receipts/new — render the receiving form.
-
#post_landed_costs ⇒ Object
POST /shipment_receipts/:id/post_landed_costs — apply the entered landed cost.
-
#preview_landed_costs ⇒ Object
GET /shipment_receipts/:id/preview_landed_costs — render the landed-cost preview screen (shows the prorated per-item bump before the user posts).
-
#void ⇒ Object
POST /shipment_receipts/:id/void — void the entire shipment receipt (returns inventory commits, reverses the GL postings).
-
#void_landed_costs ⇒ Object
POST /shipment_receipts/:id/void_landed_costs — reverse the landed-cost entries for this receipt and recalculate the parent shipment's rolled-up landed cost.
Methods included from Controllers::Showable
Methods inherited from CrmController
#access_denied, #context_id, #context_object, #crm_home_path, #current_ability, #default_url_options, #download_temp, #get_tempfile_path_for_download, #init_status_job_collector, #initialize_crm_lazy_chunks, #persist_enqueued_status_jobs, #record_not_found, #redirect_to_job_or_fallback, #render_edit_action, #set_context, #set_download_path, #stash_file_for_temp_download, #sync_admin_presence_cookie
Methods inherited from ApplicationController
#account_impersonated?, #add_to_flash, #after_sign_in_path_for, #bypass_forgery_protection?, #chat_enabled?, #cloudflare_cleared?, #default_catalog, #default_url_options, #enable_turbo_frames, #find_publication, #fix_invalid_accept_header, #init_js_utils, #is_globals_call?, #layout_by_resource, #locale_store, #redirect_to, #require_employee_for_crm, #set_base_host, #set_real_ip, #set_report_errors_for, #should_render_layout?, #stamp_impersonation_context, #warmlyyours_canada_ip?, #warmlyyours_ip?, #y
Methods included from Controllers::ReturnPathHandling
#check_for_return_path, #redirect_to_return_path_or_default
Methods included from Controllers::AnalyticsEvents
#consume_queued_analytics_events, #track_event
Methods included from Controllers::DeviceDetection
Methods included from Controllers::SubdomainDetection
#is_crm_request?, #is_www_request?, #json_request?
Methods included from Controllers::TurboSafeRedirect
Methods included from Controllers::TrackingDetection
#bot_request?, #gdpr_country?, #gdpr_country_data, #prevent_bots, #set_tracking_cookie, #track_visitor?
Methods included from Controllers::AcceleratedFileSending
#send_file_accelerated, #send_upload_accelerated
Methods included from Controllers::ErrorRendering
#excp_string, #mail_to_for_error_reporting, #render_400, #render_404, #render_406, #render_410, #render_500, #render_invalid_authenticity_token, #render_ip_spoof_error, #render_unpermitted_parameters, #safe_referer_or_fallback
Methods included from Controllers::TurnstileVerification
#load_turnstile_script_tag, #turnstile_lazy_widget, #turnstile_script_tag, #turnstile_widget, #validate_turnstile!
Methods included from Controllers::CloudflareCaching
edge_cached, #edge_cached_action?, #reset_cloudflare_cache, #set_cloudflare_cache, #skip_edge_cache!, #skip_session
Methods included from Controllers::Webpackable
#preload_webpack_fonts, #webpack_css_include, #webpack_css_url, #webpack_js_include, #wpd_is_running?
Methods included from Controllers::Localizable
#cloudflare_country_locale, #determine_request_locale, #geocoder_locale, #guest_user_locale_check, #locale_optional_www_auth_path?, #param_locale, #set_locale, #set_request_locale, #skip_localization?, #warmlyyours_ip_locale
Methods included from Controllers::Authenticable
#access_denied, #authenticate_account, #authenticate_account!, #authenticate_account_from_login_token!, #check_is_a_manager, #check_is_a_sales_manager, #check_is_an_admin, #check_is_an_employee, #check_party, #clear_mismatched_guest_user, #create_guest_user, #credentials?, #current_or_guest_user, #current_or_guest_user_id_read_only, #current_user, #devise_mapping, #fully_logged_in?, #generate_bot_id, #guest_user, #identifiable?, #init_current_user, #initialize_guest, #load_context_user, #logging_in, #resource, #resource_name, #restrict_access_for_non_employees, #scrubbed_request_path, #user_object, #warn_on_session_guest_id_leak
Methods included from ApplicationHelper
#better_number_to_currency, #check_force_logout, #check_or_cross, #check_or_times, #embedded_tab_frame_id, #error_messages, #general_disclaimer_on_product_installation_and_local_codes, #gridjs_from_html_table, #gridjs_table, #is_wy_ip, #line_break, #parent_layout, #pass_or_fail, #render_error_messages_list, #render_video_card, #resolved_auth_form_turbo_frame, #return_path_or, #safe_css_color, #set_return_path_if_present, #set_section_if_present, #tab_frame_id, #to_underscore, #track_page?, #turbo_section_wrapper, #turbo_tabs_request?, #url_on_same_domain_as_request, #widget_index_daily_focus_index_path, #working_hours?, #yes_or_no, #yes_or_no_highlighted, #yes_or_no_with_check_or_cross, #youtube_video
Methods included from UppyUploaderHelper
#file_uploader, #image_uploader, #large_file_uploader_s3, #lead_sketch_uploader, #rma_image_uploader, #rma_image_uploader_s3, #uppy_uploader, #video_uploader
Methods included from Www::ImagesHelper
#image_asset_tag, #image_asset_url
Methods included from Www::SeoHelper
#add_page_schema, #add_webpage_schema, #canada?, #company_social_links, #ensure_context_json, #json_ld_script_tag, #local_business_schema, #online_store_id, #online_store_schema, #page_main_entity, #page_main_entity_json, #render_auto_collection_page_schema, #render_collection_page_schema, #render_local_business_schema, #render_online_store_schema, #render_page_schemas, #render_page_video_schemas, #render_webpage_schema, #render_webpage_schema_with_collections, #usa?
Methods included from UrlsHelper
#catalog_breadcrumb_links, #catalog_link, #catalog_link_for_product_line, #catalog_link_for_sku, #cms_link, #delocalized_path, #path_to_sales_product_sku, #path_to_sales_product_sku_for_product_line, #path_to_sales_product_sku_for_product_line_slug, #product_line_from_catalog_link, #protocol_neutral_url, #sanitize_external_url, #valid_external_url?
Methods included from IconHelper
#account_nav_icon, #fa_icon, #star_rating_html
Instance Method Details
#assign_serial_numbers ⇒ Object
GET /shipment_receipts/:id/assign_serial_numbers — render the
serial-number entry form for items that require reservation
(heating mats / cables ship with manufacturer SNs we have to
record on receipt). Builds blank SN rows for any item that
hasn't been fully entered yet.
185 186 187 188 189 |
# File 'app/controllers/shipment_receipts_controller.rb', line 185 def assign_serial_numbers @shipment_receipt = ShipmentReceipt.find(params[:id]) @shipment_receipt_items = @shipment_receipt.shipment_receipt_items.select { |sri| sri.item.require_reservation? } @shipment_receipt_items.each { |sri| sri.build_serial_numbers unless sri.serial_numbers.to_a.sum(&:qty) == sri.quantity } end |
#confirm_landed_costs ⇒ Object
GET /shipment_receipts/:id/confirm_landed_costs — final
confirmation step before posting. Empty action; just renders
the template.
163 |
# File 'app/controllers/shipment_receipts_controller.rb', line 163 def confirm_landed_costs; end |
#create ⇒ Object
POST /shipment_receipts — receive inbound supplier shipment.
Synchronous DB work was moved into ShipmentReceiptsWorker (see
the commented-out direct path below) because the receipts form
can submit hundreds of items at once and the warehouse couldn't
tolerate the request timeout. Detects an already-enqueued
duplicate via BackgroundJobStatus so a double-submit shows the
existing job rather than creating two.
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'app/controllers/shipment_receipts_controller.rb', line 42 def create @purchase_order_shipment = PurchaseOrderShipment.find(params[:shipment_receipt][:purchase_order_shipment_id]) @shipment_receipt = ShipmentReceipt.new(params[:shipment_receipt]) :create, @shipment_receipt # If shipment_items is empty then the shipment receipt will be invalid and won't save # ShipmentReceipt.with_advisory_lock("receiving_items_pos_#{@purchase_order_shipment.id}", timeout_seconds: 0) do # @shipment_receipt.enter_receipts(params[:shipment_items]) # if @purchase_order_shipment.estimated_landed_cost.present? # @shipment_receipt.estimated_landed_cost = @shipment_receipt.prorate_estimated_landed_cost # @shipment_receipt.currency = @purchase_order_shipment.currency # end # @shipment_receipt.save # end # if @shipment_receipt.persisted? # if @shipment_receipt.serial_number_state == "awaiting_assignment" # redirect_to assign_serial_numbers_shipment_receipt_path(@shipment_receipt) # else # redirect_to purchase_order_path(@shipment_receipt.shipment_receipt_items.first.purchase_order) # end # else # render :new # end = { shipment_receipt: params[:shipment_receipt].to_hash, purchase_order_shipment_id: @purchase_order_shipment.id, shipment_items: params[:shipment_items].to_hash }.stringify_keys job_id = ShipmentReceiptsWorker.perform_async() if job_id.blank? if (job_id = BackgroundJobStatus.search(worker_klass: 'ShipmentReceiptsWorker', args: ).first&.dig(:job_id)) flash[:warning] = "A similar job was already enqueued, watching status of that job now" end end if job_id.present? redirect_to job_path(job_id) else flash[:warning] = "There was a problem queuing the job" redirect_to_return_path_or_default purchase_order_path(@shipment_receipt.shipment_receipt_items.first.purchase_order) end end |
#do_assign_serial_numbers ⇒ Object
POST /shipment_receipts/:id/do_assign_serial_numbers — persist
the entered serial numbers and route the user back to the
purchase order. Re-renders the form when assignment is
incomplete (every reservable item must have its full quantity
of SNs).
196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'app/controllers/shipment_receipts_controller.rb', line 196 def do_assign_serial_numbers @shipment_receipt = ShipmentReceipt.find(params[:id]) @shipment_receipt.assign_attributes(params[:shipment_receipt]) if @shipment_receipt.complete_serial_number_assignment flash[:info] = "New serial numbers (#{@shipment_receipt.serial_number_numbers}) created." redirect_to purchase_order_path(@shipment_receipt.shipment_receipt_items.first.purchase_order) else flash.now[:error] = "Unable to save, please provide all serial numbers." @shipment_receipt_items = @shipment_receipt.shipment_receipt_items.select { |sri| sri.item.require_reservation? } render :assign_serial_numbers, status: :unprocessable_content end end |
#edit_landed_costs ⇒ Object
GET /shipment_receipts/:id/edit_landed_costs — re-open the
landed-costs form when a receipt already has costs entered. The
form pre-fills with the existing values so the user can adjust
without re-deriving them.
93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'app/controllers/shipment_receipts_controller.rb', line 93 def edit_landed_costs @shipment_receipt = ShipmentReceipt.find(params[:id]) @landed_cost = OpenStruct.new(params[:landed_cost]) if @shipment_receipt.landed_cost.present? landed_cost = {} landed_cost[:landed_cost] = @shipment_receipt.landed_cost landed_cost[:carrier_id] = @shipment_receipt.landed_costs.actual.map(&:carrier_id).uniq.first landed_cost[:estimated] = true @landed_cost = OpenStruct.new(landed_cost) else @landed_cost = OpenStruct.new(params[:landed_cost]) end end |
#enter_landed_costs ⇒ Object
GET /shipment_receipts/:id/enter_landed_costs — render the
landed-costs form for first-time entry (carrier + total cost).
The cost is later prorated across the receipt's items by
ShipmentReceipt#enter_landed_costs.
84 85 86 87 |
# File 'app/controllers/shipment_receipts_controller.rb', line 84 def enter_landed_costs @shipment_receipt = ShipmentReceipt.find(params[:id]) @landed_cost = OpenStruct.new(params[:landed_cost]) end |
#new ⇒ Object
GET /purchase_order_shipments/:purchase_order_shipment_id/shipment_receipts/new —
render the receiving form. Pre-populates effective_date to today
so receivers don't have to fill it on every receipt.
29 30 31 32 33 |
# File 'app/controllers/shipment_receipts_controller.rb', line 29 def new @purchase_order_shipment = PurchaseOrderShipment.find(params[:purchase_order_shipment_id]) @shipment_receipt = ShipmentReceipt.new(purchase_order_shipment_id: @purchase_order_shipment.id, effective_date: Date.current) :create, @shipment_receipt end |
#post_landed_costs ⇒ Object
POST /shipment_receipts/:id/post_landed_costs — apply the
entered landed cost. If the receipt already had costs they're
voided first so we don't double-post. Subtracts the
estimated-landed-cost figure (already booked at receive time) so
only the delta hits the GL. Updates the parent shipment's
rolled-up landed-cost so the report stays accurate.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'app/controllers/shipment_receipts_controller.rb', line 113 def post_landed_costs @shipment_receipt = ShipmentReceipt.find(params[:id]) @shipment_receipt.void_landed_costs if @shipment_receipt.landed_cost.present? estimated_landed_cost = @shipment_receipt.estimated_landed_cost.nil? ? 0 : @shipment_receipt.estimated_landed_cost @landed_cost = OpenStruct.new(params[:landed_cost]) if @landed_cost.landed_cost && @landed_cost.landed_cost.to_i >= 0 && @landed_cost.carrier_id landed_cost_calc = @landed_cost.landed_cost.to_f - estimated_landed_cost @shipment_receipt.enter_landed_costs(landed_cost_calc.to_s, @landed_cost.carrier_id) pos = @shipment_receipt.purchase_order_shipment if pos.shipment_receipts.map(&:landed_cost).any? landed_cost = pos.shipment_receipts.filter_map(&:landed_cost).sum estimated_landed_cost = pos.shipment_receipts.filter_map { |sr| sr.landed_cost.present? ? sr.estimated_landed_cost : nil }.sum pos.update(landed_cost: landed_cost + estimated_landed_cost) else pos.update(landed_cost: nil) end redirect_to purchase_order_path(@shipment_receipt.shipment_receipt_items.first.purchase_order) else flash.now[:error] = "You must specify a carrier and a landed cost of 0 or more" render :enter_landed_costs, status: :unprocessable_content end end |
#preview_landed_costs ⇒ Object
GET /shipment_receipts/:id/preview_landed_costs — render the
landed-cost preview screen (shows the prorated per-item bump
before the user posts).
158 |
# File 'app/controllers/shipment_receipts_controller.rb', line 158 def preview_landed_costs; end |
#void ⇒ Object
POST /shipment_receipts/:id/void — void the entire shipment
receipt (returns inventory commits, reverses the GL postings).
The model returns a {success:, message:} hash so the flash
surfaces gateway-side reasons for refusal.
169 170 171 172 173 174 175 176 177 178 |
# File 'app/controllers/shipment_receipts_controller.rb', line 169 def void @shipment_receipt = ShipmentReceipt.find(params[:id]) res = @shipment_receipt.void_shipment_receipt if res["success"] == false flash[:error] = res["message"] else flash[:info] = res["message"] end redirect_to shipment_receipt_path(@shipment_receipt) end |
#void_landed_costs ⇒ Object
POST /shipment_receipts/:id/void_landed_costs — reverse the
landed-cost entries for this receipt and recalculate the
parent shipment's rolled-up landed cost. Used when accounting
needs to back out a wrongly-attributed freight bill.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'app/controllers/shipment_receipts_controller.rb', line 140 def void_landed_costs @shipment_receipt = ShipmentReceipt.find(params[:id]) @shipment_receipt.void_landed_costs pos = @shipment_receipt.purchase_order_shipment if pos.shipment_receipts.map(&:landed_cost).any? landed_cost = pos.shipment_receipts.filter_map(&:landed_cost).sum estimated_landed_cost = pos.shipment_receipts.filter_map { |sr| sr.landed_cost.present? ? sr.estimated_landed_cost : nil }.sum pos.update(landed_cost: landed_cost + estimated_landed_cost) else pos.update(landed_cost: nil) end flash[:info] = "Landed costs have been voided for this shipment receipt" redirect_to @shipment_receipt end |