Class: Edi::BaseOrchestrator
- Inherits:
-
Object
- Object
- Edi::BaseOrchestrator
- Extended by:
- Memery
- Defined in:
- app/services/edi/base_orchestrator.rb
Overview
Service object: base orchestrator.
Direct Known Subclasses
Amazon::Orchestrator, AmazonVc::Orchestrator, Commercehub::Orchestrator, Houzz::Orchestrator, Menard::Orchestrator, MftGateway::Orchestrator, MiraklSeller::Orchestrator, Openai::Orchestrator, ResellerInventory::Orchestrator, Walmart::Orchestrator, Wayfair::Orchestrator
Constant Summary collapse
- ORCHESTRATORS =
Orchestrators.
['Edi::Amazon::Orchestrator', 'Edi::Commercehub::Orchestrator', 'Edi::Houzz::Orchestrator', 'Edi::Wayfair::Orchestrator', 'Edi::AmazonVc::Orchestrator', 'Edi::MiraklSeller::Orchestrator', 'Edi::MftGateway::Orchestrator', 'Edi::Walmart::Orchestrator', 'Edi::Menard::Orchestrator', 'Edi::Openai::Orchestrator', 'Edi::ResellerInventory::Orchestrator'].freeze
- RECOMMENDED_EXECUTE_FLOW_EVERY_X_HOUR =
Recommended execute flow every x hour.
[1, 2, 3, 4, 6, 8, 12, 24].freeze
- DEFAULT_PENDING_DISCONTINUE_LIFETIME =
Default pending discontinue lifetime.
1.day
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
Delegated Instance Attributes collapse
-
#customer_catalog ⇒ Object
Alias for Customer#catalog.
Class Method Summary collapse
- .all_orchestrators_class ⇒ Object
- .build(partner_config_key, options = {}) ⇒ Object
-
.build_customer_id_to_partner_key_map(partners) ⇒ Hash
Pure two-pass builder split out of BaseOrchestrator.customer_id_to_partner_key_map so tests can drive it with a fixture WITHOUT stubbing the memoized
partners(see the note above). -
.cached_build(partner_config_key, options = {}) ⇒ Object
Returns a cached orchestrator instance for the given partner key This avoids expensive repeated instantiation of orchestrators with dynamic accessors.
-
.cached_orchestrators ⇒ Object
Request/job-scoped cache of orchestrator instances by partner key.
-
.catalog_id_to_pending_discontinue_lifetime ⇒ Object
Returns a hash of { catalog_id => ActiveSupport::Duration } for all active orchestrators that define a custom pending_discontinue_lifetime.
- .catalog_ids_edi_enabled ⇒ Object
-
.customer_id_to_partner_key_map ⇒ Object
Builds a lookup hash from customer_id to partner config key for fast lookups Handles both single customer_id values and multi-customer partner configurations.
- .customer_ids_edi_enabled ⇒ Object
- .customer_ids_with_invoice_message_enabled ⇒ Object
-
.execute_discontinue_flow(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) ⇒ Object
Executes the discontinue flow for EDI orchestrators.
-
.execute_flow(flow, orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) ⇒ Object
Executes the specified flow (inventory, order, or product data) for the given orchestrator(s).
-
.execute_inventory_flow(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) ⇒ Object
Executes the inventory flow for EDI orchestrators.
-
.execute_listing_message_feed_flow(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) ⇒ Object
Executes the listing message flow for EDI orchestrators.
- .execute_order_flow(options = {}) ⇒ Object
-
.execute_price_flow(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) ⇒ Object
Executes the price flow for EDI orchestrators.
- .execute_product_data_flow(options = {}) ⇒ Object
- .orchestrator_for_customer_id(customer_id, use_cache: true) ⇒ Object
- .orchestrators(options = {}) ⇒ Object
- .partners ⇒ Object
Instance Method Summary collapse
-
#confirm_outbound_processing? ⇒ Boolean
By default we don't require a two stage processing (ready -> processing -> complete).
- #customer(segment = nil) ⇒ Object
- #customer_ids ⇒ Object
-
#customers ⇒ Object
Returns customers (or single customer) associated with an orchestrator as an active relation.
- #execute_inventory_flow ⇒ Object
- #execute_order_flow ⇒ Object
- #execute_price_flow ⇒ Object
- #execute_product_data_flow ⇒ Object
-
#ignore_back_orders ⇒ Object
By default back orders are not ignored.
-
#initialize(partner, options = {}) ⇒ BaseOrchestrator
constructor
A new instance of BaseOrchestrator.
- #inventory_message_enabled? ⇒ Boolean
- #pending_discontinue_lifetime ⇒ Object
- #price_message_enabled? ⇒ Boolean
- #product_data_enabled? ⇒ Boolean
-
#return_notification_message_enabled? ⇒ Boolean
Default false for orchestrators that don't handle inbound return notifications (inventory-only feeds, push-only partners).
-
#should_execute_flow?(flow) ⇒ Boolean
flow is in the format of execute_inventory_flow or execute_price_flow.
-
#should_execute_order_flow? ⇒ Boolean
Determines if the order flow should run.
-
#should_execute_product_data_flow? ⇒ Boolean
Determines if the product data flow should run.
- #test_mode? ⇒ Boolean
Constructor Details
#initialize(partner, options = {}) ⇒ BaseOrchestrator
Returns a new instance of BaseOrchestrator.
348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
# File 'app/services/edi/base_orchestrator.rb', line 348 def initialize(partner, = {}) # `try` guards against a non-symbolizable partner (e.g. a Hash passed by a # mis-invoked `rails runner` one-liner) — fail fast with a clear message # instead of `NoMethodError: undefined method 'to_sym'` (AppSignal #5014). @config = self.class.partners[partner.try(:to_sym)] raise ArgumentError, "Unrecognized EDI partner: #{partner.inspect}" unless @config @config.each do |name, val| singleton_class.send :attr_accessor, name.to_sym public_send :"#{name}=", val end @options = @logger = [:logger] || Rails.logger end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
6 7 8 |
# File 'app/services/edi/base_orchestrator.rb', line 6 def config @config end |
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
6 7 8 |
# File 'app/services/edi/base_orchestrator.rb', line 6 def logger @logger end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
6 7 8 |
# File 'app/services/edi/base_orchestrator.rb', line 6 def @options end |
Class Method Details
.all_orchestrators_class ⇒ Object
20 21 22 |
# File 'app/services/edi/base_orchestrator.rb', line 20 def all_orchestrators_class ORCHESTRATORS.map(&:constantize) end |
.build(partner_config_key, options = {}) ⇒ Object
79 80 81 82 83 84 85 |
# File 'app/services/edi/base_orchestrator.rb', line 79 def build(partner_config_key, = {}) # Find the orchestrator for this partner key orchestrator_class = all_orchestrators_class.find { |o| o.partners.key?(partner_config_key.to_sym) } return orchestrator_class.new(partner_config_key, ) if orchestrator_class raise "Cannot determine orchestrator class for partner #{partner_config_key}" end |
.build_customer_id_to_partner_key_map(partners) ⇒ Hash
Pure two-pass builder split out of customer_id_to_partner_key_map so
tests can drive it with a fixture WITHOUT stubbing the memoized
partners (see the note above). Not memoized — safe to call directly.
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 |
# File 'app/services/edi/base_orchestrator.rb', line 49 def build_customer_id_to_partner_key_map(partners) map = {} # The two passes are deliberately separate and MUST NOT be combined: # collapsing them is exactly the PR #480 regression that made every # Hash-style multi-customer partner (Rona/Lowes/Reno) invisible, because # the first pass `next if ...is_a?(Hash)` and the second pass # `next unless ...is_a?(Hash)` cannot share one iteration. # rubocop:disable Style/CombinableLoops # First pass: single customer_id partners (higher priority) partners.each do |key, config| next unless config[:active] next if config[:inventory_feed_only] # push-only inventory feeds never answer a customer_id lookup next if config[:customer_id].is_a?(Hash) # Skip multi-customer partners in first pass map[config[:customer_id]] = key if config[:customer_id] end # Second pass: multi-customer partners (lower priority, only if not already mapped) partners.each do |key, config| next unless config[:active] next if config[:inventory_feed_only] next unless config[:customer_id].is_a?(Hash) config[:customer_id].values.each do |cid| map[cid] ||= key # Only set if not already mapped by single-customer partner end end # rubocop:enable Style/CombinableLoops map end |
.cached_build(partner_config_key, options = {}) ⇒ Object
Returns a cached orchestrator instance for the given partner key
This avoids expensive repeated instantiation of orchestrators with dynamic accessors
100 101 102 103 |
# File 'app/services/edi/base_orchestrator.rb', line 100 def cached_build(partner_config_key, = {}) cache_key = [partner_config_key.to_sym, .hash].join('_') cached_orchestrators[cache_key] ||= build(partner_config_key, ) end |
.cached_orchestrators ⇒ Object
Request/job-scoped cache of orchestrator instances by partner key.
Backed by CurrentScope so it is automatically reset between web
requests (Rails) and Sidekiq jobs (Sidekiq::CurrentAttributes
middleware). The previous implementation used a class-level instance
variable (@cached_orchestrators ||= {}) which is shared across
threads and never reset -- so it both leaked memory unboundedly and
held stale partner config across deploys/reloads.
94 95 96 |
# File 'app/services/edi/base_orchestrator.rb', line 94 def cached_orchestrators CurrentScope.edi_orchestrator_cache ||= {} end |
.catalog_id_to_pending_discontinue_lifetime ⇒ Object
Returns a hash of { catalog_id => ActiveSupport::Duration } for all active
orchestrators that define a custom pending_discontinue_lifetime. Used by
Maintenance::ItemMaintenance to apply per-partner wait times.
411 412 413 414 415 416 417 418 419 420 421 422 423 |
# File 'app/services/edi/base_orchestrator.rb', line 411 def self.catalog_id_to_pending_discontinue_lifetime map = {} orchestrators.each do |o| next unless o.active lifetime = o.pending_discontinue_lifetime next if lifetime == DEFAULT_PENDING_DISCONTINUE_LIFETIME catalog_id = o.try(:catalog_id) map[catalog_id] = lifetime if catalog_id end map end |
.catalog_ids_edi_enabled ⇒ Object
142 143 144 |
# File 'app/services/edi/base_orchestrator.rb', line 142 def catalog_ids_edi_enabled Customer.where(id: customer_ids_edi_enabled).pluck(:catalog_id).uniq.sort end |
.customer_id_to_partner_key_map ⇒ Object
Builds a lookup hash from customer_id to partner config key for fast lookups
Handles both single customer_id values and multi-customer partner configurations
38 39 40 |
# File 'app/services/edi/base_orchestrator.rb', line 38 def customer_id_to_partner_key_map build_customer_id_to_partner_key_map(partners) end |
.customer_ids_edi_enabled ⇒ Object
125 126 127 |
# File 'app/services/edi/base_orchestrator.rb', line 125 def customer_ids_edi_enabled partners.values.select { |v| v[:customer_id].try(:values) || v[:customer_id] }.map { |v| v[:customer_id].try(:values) || v[:customer_id] }.flatten.uniq.sort end |
.customer_ids_with_invoice_message_enabled ⇒ Object
130 131 132 133 134 135 136 137 138 139 |
# File 'app/services/edi/base_orchestrator.rb', line 130 def Rails.cache.fetch('edi/customer_ids_with_invoice_message_enabled', expires_in: 1.hour) do partners.keys.filter_map do |key| o = cached_build(key) next unless o.respond_to?(:invoice_message_enabled?) && o. Array(o.config[:customer_id].is_a?(Hash) ? o.config[:customer_id].values : o.config[:customer_id]) end.flatten.compact.uniq.sort end end |
.execute_discontinue_flow(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) ⇒ Object
Executes the discontinue flow for EDI orchestrators.
Picks up pending_discontinue catalog items and sends DELETE via SP-API.
orchestrator_name - The name of a specific orchestrator to run, optional.
partner - The partner key to run for, optional.
logger - The logger to use.
trial_run - If true, will not send real requests.
196 197 198 |
# File 'app/services/edi/base_orchestrator.rb', line 196 def self.execute_discontinue_flow(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) execute_flow(:execute_discontinue_flow, orchestrator_name:, partner:, logger:, trial_run:) end |
.execute_flow(flow, orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) ⇒ Object
Executes the specified flow (inventory, order, or product data)
for the given orchestrator(s). Allows filtering by orchestrator name and partner.
Logs execution and returns results.
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'app/services/edi/base_orchestrator.rb', line 203 def self.execute_flow(flow, orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) valid_flows = %i[execute_inventory_flow execute_order_flow execute_product_data_flow execute_price_flow execute_listing_message_feed_flow execute_discontinue_flow] raise "Invalid flow option, must be one of #{valid_flows.join(', ')}" unless flow.in?(valid_flows) results = [] all_orchestrators_class.each do |oc| next if orchestrator_name.present? && oc.name != orchestrator_name logger.tagged oc.name do oc.orchestrators.each do |orchestrator| next if partner.present? && orchestrator.partner.to_s != partner logger.tagged orchestrator.partner do logger.tagged flow do logger.info 'started' begin result = if orchestrator.should_execute_flow?(flow) && orchestrator.respond_to?(flow) trial_run ? :trial_run : orchestrator.send(flow) else :scheduled_skip end logger.info "Result: #{loggable_result(result)}" results << { orchestrator_class: oc.name, partner: orchestrator.partner, flow:, result: } rescue Exception => e msg = "#{oc.name} #{orchestrator.partner} #{flow} exception. #{e}" # Enhanced error logging with detailed context ErrorReporting.error(e, { orchestrator_class: oc.name, partner: orchestrator.partner, flow: flow, error_type: 'orchestrator_execution_error', orchestrator_name: orchestrator.class.name, flow_method: flow, exception_class: e.class.name, exception_message: e., backtrace: e.backtrace&.first(10), message: msg }) logger.error msg # Add error result to results array instead of failing silently results << { orchestrator_class: oc.name, partner: orchestrator.partner, flow:, result: :error, error: e., error_class: e.class.name } end logger.info 'completed' end end end end end results end |
.execute_inventory_flow(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) ⇒ Object
Executes the inventory flow for EDI orchestrators.
orchestrator_name - The name of a specific orchestrator to run, optional.
partner - The partner key to run for, optional.
logger - The logger to use.
trial_run - If true, will not send real requests.
165 166 167 |
# File 'app/services/edi/base_orchestrator.rb', line 165 def self.execute_inventory_flow(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) execute_flow(:execute_inventory_flow, orchestrator_name:, partner:, logger:, trial_run:) end |
.execute_listing_message_feed_flow(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) ⇒ Object
Executes the listing message flow for EDI orchestrators.
orchestrator_name - The name of a specific orchestrator to run, optional.
partner - The partner key to run for, optional.
logger - The logger to use.
trial_run - If true, will not send real requests.
185 186 187 |
# File 'app/services/edi/base_orchestrator.rb', line 185 def self.(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) execute_flow(:execute_listing_message_feed_flow, orchestrator_name:, partner:, logger:, trial_run:) end |
.execute_order_flow(options = {}) ⇒ Object
261 262 263 264 265 |
# File 'app/services/edi/base_orchestrator.rb', line 261 def self.execute_order_flow( = {}) # Queue for Ship confirm what can be confirmed right away # Edi::ShipConfirm.new.process # NO MORE AUTO SHIP CONFIRM orchestrators().each(&:execute_order_flow) end |
.execute_price_flow(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) ⇒ Object
Executes the price flow for EDI orchestrators.
orchestrator_name - The name of a specific orchestrator to run, optional.
partner - The partner key to run for, optional.
logger - The logger to use.
trial_run - If true, will not send real requests.
175 176 177 |
# File 'app/services/edi/base_orchestrator.rb', line 175 def self.execute_price_flow(orchestrator_name: nil, partner: nil, logger: Rails.logger, trial_run: false) execute_flow(:execute_price_flow, orchestrator_name:, partner:, logger:, trial_run:) end |
.execute_product_data_flow(options = {}) ⇒ Object
328 329 330 |
# File 'app/services/edi/base_orchestrator.rb', line 328 def self.execute_product_data_flow( = {}) orchestrators().each(&:execute_product_data_flow) end |
.orchestrator_for_customer_id(customer_id, use_cache: true) ⇒ Object
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'app/services/edi/base_orchestrator.rb', line 105 def orchestrator_for_customer_id(customer_id, use_cache: true) # 041619 Ramie: match first on single customer id partners, then dig into multi customer partners # this is necessary to properly match Amazon Vendor Central vendor partners: there is a single EDI entity partner: # :amazon_vendor_central_direct_fulfillment (for both WAX7V and WAT4D) # but two single partners for vendors WAX7V and WAT4D: # :amazon_vendor_central_direct_fulfillment_us_WAX7V and # :amazon_vendor_central_direct_fulfillment_us_WAT4D # and we want to drill down to one of the correct single customer id partners above, not the multi customer :amazon_vendor_central_direct_fulfillment partner (which is really only set up for inventory) # Use the cached lookup map for O(1) partner key lookups instead of O(n) detect operations partner_config_key = customer_id_to_partner_key_map[customer_id] return unless partner_config_key use_cache ? cached_build(partner_config_key) : build(partner_config_key) end |
.orchestrators(options = {}) ⇒ Object
121 122 123 |
# File 'app/services/edi/base_orchestrator.rb', line 121 def orchestrators( = {}) partners.keys.map { |partner| new(partner, ) } end |
.partners ⇒ Object
25 26 27 |
# File 'app/services/edi/base_orchestrator.rb', line 25 def partners all_orchestrators_class.map(&:partners).reduce({}, :merge) end |
Instance Method Details
#confirm_outbound_processing? ⇒ Boolean
By default we don't require a two stage processing (ready -> processing -> complete)
426 427 428 |
# File 'app/services/edi/base_orchestrator.rb', line 426 def confirm_outbound_processing? false end |
#customer(segment = nil) ⇒ Object
367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
# File 'app/services/edi/base_orchestrator.rb', line 367 def customer(segment = nil) raise 'Orchestrator requires a segment for this partner to determine customer' if customer_id.is_a?(Hash) && segment.nil? if segment.present? && customer_id.is_a?(Hash) segment_cust_id = customer_id[segment.to_s.downcase.to_sym] segment_cust_id = customer_id[segment.to_s.to_sym] if segment_cust_id.nil? # In case we use uppercase keys cust = Customer.where(id: segment_cust_id).first elsif customer_id cust = Customer.where(id: customer_id).first end return cust if cust raise 'Orchestrator is unable to find a customer' end |
#customer_catalog ⇒ Object
Alias for Customer#catalog
15 |
# File 'app/services/edi/base_orchestrator.rb', line 15 delegate :catalog, to: :customer, prefix: true |
#customer_ids ⇒ Object
388 389 390 391 392 393 394 395 396 397 398 |
# File 'app/services/edi/base_orchestrator.rb', line 388 def customer_ids if respond_to?(:customer_id) if customer_id.respond_to?(:values) customer_id.values.uniq else [customer_id] end else [] end end |
#customers ⇒ Object
Returns customers (or single customer) associated with an orchestrator
as an active relation
384 385 386 |
# File 'app/services/edi/base_orchestrator.rb', line 384 def customers Customer.where(id: customer_ids) end |
#execute_inventory_flow ⇒ Object
336 337 338 |
# File 'app/services/edi/base_orchestrator.rb', line 336 def execute_inventory_flow # Implement me in subclass end |
#execute_order_flow ⇒ Object
332 333 334 |
# File 'app/services/edi/base_orchestrator.rb', line 332 def execute_order_flow # Implement me in subclass end |
#execute_price_flow ⇒ Object
340 341 342 |
# File 'app/services/edi/base_orchestrator.rb', line 340 def execute_price_flow # Implement me in subclass end |
#execute_product_data_flow ⇒ Object
344 345 346 |
# File 'app/services/edi/base_orchestrator.rb', line 344 def execute_product_data_flow # Implement me in subclass end |
#ignore_back_orders ⇒ Object
By default back orders are not ignored
431 432 433 |
# File 'app/services/edi/base_orchestrator.rb', line 431 def ignore_back_orders false end |
#inventory_message_enabled? ⇒ Boolean
285 286 287 |
# File 'app/services/edi/base_orchestrator.rb', line 285 def try(:inventory_message_enabled).to_b end |
#pending_discontinue_lifetime ⇒ Object
403 404 405 406 |
# File 'app/services/edi/base_orchestrator.rb', line 403 def pending_discontinue_lifetime val = try(:pending_discontinue_lifetime_duration) val.is_a?(ActiveSupport::Duration) ? val : DEFAULT_PENDING_DISCONTINUE_LIFETIME end |
#price_message_enabled? ⇒ Boolean
277 278 279 |
# File 'app/services/edi/base_orchestrator.rb', line 277 def try(:price_message_enabled).to_b end |
#product_data_enabled? ⇒ Boolean
281 282 283 |
# File 'app/services/edi/base_orchestrator.rb', line 281 def product_data_enabled? try(:product_data_enabled).to_b end |
#return_notification_message_enabled? ⇒ Boolean
Default false for orchestrators that don't handle inbound return notifications
(inventory-only feeds, push-only partners). Returns-capable orchestrators
(Amazon, Walmart, Wayfair, …) override this. Prevents a NoMethodError when a
customer_id resolves to a non-returns orchestrator (AppSignal #6069).
293 294 295 |
# File 'app/services/edi/base_orchestrator.rb', line 293 def try(:return_notification_message_enabled).to_b end |
#should_execute_flow?(flow) ⇒ Boolean
flow is in the format of execute_inventory_flow or execute_price_flow
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 |
# File 'app/services/edi/base_orchestrator.rb', line 299 def should_execute_flow?(flow) flow_every_x_hour_sym = :"#{flow}_every_x_hour" return true unless respond_to? flow_every_x_hour_sym every_x_hour = send(flow_every_x_hour_sym).to_i current_hour = Time.current.hour if every_x_hour > 0 && every_x_hour <= 24 # valid integral value, let's use it # warn if it's not exactly one of the recommended value, i.e. integral factors of 24 unless RECOMMENDED_EXECUTE_FLOW_EVERY_X_HOUR.include?(every_x_hour) msg = "EDI #{self.class} partner: #{partner} has a #{flow_every_x_hour_sym} value of #{every_x_hour} which is not one of the recommended values: #{RECOMMENDED_EXECUTE_FLOW_EVERY_X_HOUR}, inventory may not be sent at exactly the desired frequency" ErrorReporting.warning(msg) Rails.logger.info(msg) end # but do go ahead and send per the every_x_hour integral value return true if current_hour.modulo(every_x_hour) == 0 else # invalid value, error but do send it at least once a day as a fall back msg = "EDI #{self.class} partner: #{partner} has an invalid #{flow_every_x_hour_sym} value of #{every_x_hour}. Valid values are between #{RECOMMENDED_EXECUTE_FLOW_EVERY_X_HOUR.min} and #{RECOMMENDED_EXECUTE_FLOW_EVERY_X_HOUR.max}, as a failsafe fallback, inventory will only be sent once per day!" ErrorReporting.error(msg) Rails.logger.error(msg) return true if current_hour.modulo(24) == 0 end false end |
#should_execute_order_flow? ⇒ Boolean
Determines if the order flow should run
268 269 270 |
# File 'app/services/edi/base_orchestrator.rb', line 268 def should_execute_order_flow? true end |
#should_execute_product_data_flow? ⇒ Boolean
Determines if the product data flow should run
273 274 275 |
# File 'app/services/edi/base_orchestrator.rb', line 273 def should_execute_product_data_flow? true end |
#test_mode? ⇒ Boolean
363 364 365 |
# File 'app/services/edi/base_orchestrator.rb', line 363 def test_mode? Rails.env.development? end |