# frozen_string_literal: true require_relative '../api_resource' module ErpIntegration module Fulfil module Resources class SalesOrder < ApiResource self.model_name = 'sale.sale' class MissingIdempotencyKey < ErpIntegration::Error def initialize super( '[ERP Integration] Missing the required reference attribute. ' \ 'Setting the reference prevents Fulfil from processing the same sales ' \ "order twice. For this reason, it's required to provide it as a safeguard." ) end end # Allows cancelling the entire sales order in Fulfil. # @param id [Integer|String] The ID of the to be cancelled order. # @return [boolean] Whether the sales order was cancelled successfully or not. def cancel(id) client.put("model/sale.sale/#{id}/cancel") true # Fulfil will return an 400 (a.k.a. "Bad Request") status code when a sales order couldn't # be cancelled. If a sales order isn't cancellable by design, no exception should be raised. # # See the Fulfil's documentation for more information: # https://developers.fulfil.io/rest_api/model/sale.sale/#cancel-a-sales-order rescue ErpIntegration::HttpError::BadRequest false # Workaround: Fulfil api does not return a json when status code is 200 (a.k.a. "Ok") # and faraday is having an error when trying to parse it. Let's skip the parse error # and move on. rescue Faraday::ParsingError true end # Confirm the order on Fulfil. # @param id [Integer|String] The ID of the to be confirmed order. # @return [boolean] Whether the sales order was confirmed successfully or not. def confirm(id) client.put("model/sale.sale/#{id}/confirm") true # Fulfil will return an 400 (a.k.a. "Bad Request") status code when a sales order couldn't # be confirmed. rescue ErpIntegration::HttpError::BadRequest false # Workaround: Fulfil api does not return a json when status code is 200 (a.k.a. "Ok") # and faraday is having an error when trying to parse it. Let's skip the parse error # and move on. rescue Faraday::ParsingError true end # Creates the sales order in one API call in Fulfil. # # Fulfil allows two ways of creating a new sales order. Through their # regular/generic API endpoint just like any other resource or through the # sales channel. # # The benefit of using the Sales Channel route is it allows creating the sales # # @see https://developers.fulfil.io/guides/creating-orders/#create-order-api # # The sales order number is used as an idempotency key for Fulfil to prevent # sales orders from being processed twice. Due to that it's a required attribute. # # @see https://developers.fulfil.io/guides/creating-orders/#channel_identifier # # @param sales_channel [String, Integer] The ID of the sales channel in Fulfil. # @param attributes [Hash] The attributes of the sales order # @return [ErpIntegration::SalesOrder] def create_for(sales_channel, attributes:) raise MissingIdempotencyKey if attributes['reference'].blank? && attributes[:reference].blank? ErpIntegration::SalesOrder.new( client.put("model/sale.channel/#{sales_channel}/create_order", [attributes]) ) end # Allows duplicating the entire sales order in Fulfil. # @param id [Integer|String] The ID of the to be duplicated order. # @return [Array|boolean] Whether the sales order was duplicated successfully or not. def duplicate(id) duplicated_order_id = client.put("model/sale.sale/#{id}/copy").first ErpIntegration::SalesOrder.new(id: duplicated_order_id) # Fulfil will return an 400 (a.k.a. "Bad Request") status code when a sales order couldn't # be duplicated. rescue ErpIntegration::HttpError::BadRequest false end # Process the order on Fulfil. # @param id [Integer|String] The ID of the to be processed order. # @return [boolean] Whether the sales order was processed successfully or not. def process(id) client.put("model/sale.sale/#{id}/process") true # Fulfil will return an 400 (a.k.a. "Bad Request") status code when a sales order couldn't # be processed. rescue ErpIntegration::HttpError::BadRequest false # Workaround: Fulfil api does not return a json when status code is 200 (a.k.a. "Ok") # and faraday is having an error when trying to parse it. Let's skip the parse error # and move on. rescue Faraday::ParsingError true end # Creates a return order in Fulfil. # # @param id [Integer, String] The ID of the sales order # @param options [Hash] The attributes needed for the return. def return!(id, options) client.put("model/sale.sale/#{id}/return_order", options) rescue ErpIntegration::HttpError::BadRequest false end end end end end