This gem sends data to Amazon. However, its missing one data element that I need to send. Basically the declared value of the item. I am trying to monkey patch this method to also send the declared value.
The method I'm using inside this gem is create_fulfillment_order here is a link to the method, and the method is also pasted below. What I need to do is change the items struct from this:
(:seller_sku, :seller_fulfillment_order_item_id, :quantity)
to this:
(:seller_sku, :seller_fulfillment_order_item_id, :quantity, :per_unit_declared_value)
And then this is the complete code for the method
def create_fulfillment_order(seller_fulfillment_order_id, displayable_order_id, displayable_order_date_time, displayable_order_comment, shipping_speed_category, destination_address, items, opts = {})
if opts.key?(:cod_settings)
opts['CODSettings'] = opts.delete(:cod_settings)
end
operation('CreateFulfillmentOrder')
.add(
opts.merge(
'SellerFulfillmentOrderId' => seller_fulfillment_order_id,
'DisplayableOrderId' => displayable_order_id,
'DisplayableOrderDateTime' => displayable_order_date_time,
'DisplayableOrderComment' => displayable_order_comment,
'ShippingSpeedCategory' => shipping_speed_category,
'DestinationAddress' => destination_address,
'Items' => items
)
)
.structure!('Items', 'member')
.structure!('NotificationEmailList', 'member')
run
end
I call the method like this:
client = MWS::FulfillmentOutboundShipment::Client.new(
marketplace_id: "XXXXXX",
merchant_id: "XXXXX",
aws_access_key_id: "XXXX",
aws_secret_access_key: "XXXXX+",
auth_token: "XXXXXX")
Address = Struct.new(:name, :line_1, :line_2, :line_3, :city, :state_or_province_code,
:country_code, :postal_code)
address = Address.new("Todd T", "19712 50th Ave W", "#5", "", "Lynnwood","WA" ,"US" , "98036" )
Value = Struct.new(:currency_code, :value)
value = Value.new("CAD", "10")
Item = Struct.new(:seller_sku, :seller_fulfillment_order_item_id, :quantity, :per_unit_declard_value)
sku = []
first = Item.new("636391317719", "s2", 1, value)
sku << first
begin
client.create_fulfillment_order("z536", "z536", Time.now.getutc, "Thank You", "Standard", address, sku)
rescue Exception => e
pp e.response
end
The error I'm getting is The request must contain the parameter PerUnitDeclaredValue.
Related
I am practicing with apis in RoR. I am trying to save only a few items from the api call id, length, dip, name but how do I parse it and save the fields that I need and do they need to be in params? Currently the api call data is not in params.
On button click I want to have those fields listed above save into the db
routes
root 'welcome#index'
post 'search_campaigns', to: 'campaigns#search_all_campaigns'
my model
class Campaign < ApplicationRecord
def self.get_your_campaigns
uri = URI.parse("https://example.site/api/v2/users")
request = Net::HTTP::Get.new(uri)
request.content_type = "application/json"
request.basic_auth("example#email.com", "238urfs393kmdsb2189aead01")
req_options = {
use_ssl: uri.scheme == "https",
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
return JSON.parse(response.body)
end
end
controller
class CampaignsController < ApplicationController
def search_all_campaigns
#campaigns = Campaign.get_your_campaigns
redirect_to root_path
end
end
view
<%= button_to 'Get All Campaigns', search_campaigns_path %>
This how the api call data looks
[{"id"=>2758, "dip"=>"2.0", "length"=>10, "name"=>"Cereal", "total_remaining"=>100, "status"=>6, "is_retarget"=>false}, {"id"=>278563, "dip"=>"1.25", "length"=>2, "name"=>"Pizza", "total_remaining"=>123, "status"=>6, "supplier_link"=>"http://www.developingmedia.com/adhoc.php?id=", "incidence"=>50, , "days_in_field"=>5, "max_daily_completes"=>nil, "is_retarget"=>false}, {"id"=>278564, "dip"=>"4.25", "length"=>25, "name"=>"California", "days_in_field"=>5,}]
You say the API and therefore you Campaign.get_your_campaigns method returns a Hashthat looks like this:
[
{
"id" => 2758,
"dip" => "2.0",
"length" => 10,
"name" => "Cereal",
"total_remaining" => 100,
"status" => 6,
"is_retarget" => false
},
{
"id" => 278563,
"dip" => "1.25",
"length" => 2,
"name" => "Pizza",
"total_remaining" => 123,
"status" => 6,
"supplier_link" => "http://www.developingmedia.com/adhoc.php?id=",
"incidence" => 50, ,
"days_in_field" => 5,
"max_daily_completes" => nil,
"is_retarget" => false
},
{
"id" => 278564,
"dip" => "4.25",
"length" => 25,
"name" => "California",
"days_in_field" => 5,
}
]
You can use Hash#slice to extract only the attributes you are interested in. And then pass those attributes one after the other to the create method:
campaigns_hashes = Campaign.get_your_campaigns
campaigns_attributes = campaigns_hashes.map { |hash| hash.slice(:id, :name, :length, :dip) }
campaigns = campaigns_attributes.each { |attributes| Campaign.create(attributes) }
Note: You will very likely need to add some error handling to this, for example, to deal with invalid data returned from the API or the handle records that have already been imported to avoid duplicates.
I'm trying to use the Peddler gem to create outbound fulfillments in MWS.
The only feedback I'm getting is Excon::Error::BadRequest (Expected(200) <=> Actual(400 Bad Request) hence it's a little hard to figure out what's going wrong. Here's the line that calls the API (with the values parsed):
#client.create_fulfillment_order("186", "186", 2016-08-01T07:35:48Z, "Test shipment number: 186", "Standard", {"Name"=>"Bert the Destroyer", "Line1"=>"Teststreet", "Line2"=>"123", "Line3"=>"", "DistrictOrCounty"=>"", "City"=>"Testcity", "StateOrProvinceCode"=>"CO", "CountryCode"=>"US", "PostalCode"=>"60401", "PhoneNumber"=>"12345678"}, [{"SellerSKU"=>"4785000045", "SellerFulfillmentOrderItemId"=>"4785000045", "Quantity"=>15}], {:fulfillment_policy=>"FillAll", :notification_email_list=>["bertthedestroyer#gmail.com"]})
I can't seem to figure out how to get a 200 back. Can anyone help?
The actual code:
address = {
"Name" => shipment.order.ship_to_name.to_s,
"Line1" => shipment.order.ship_to_address_1.to_s,
"Line2" => shipment.order.ship_to_address_2.to_s,
"Line3" => "",
"DistrictOrCounty" => "",
"City" => shipment.order.ship_to_city.to_s,
"StateOrProvinceCode" => shipment.order.ship_to_state_code.to_s,
"CountryCode" => shipment.order.ship_to_country_code.to_s,
"PostalCode" => shipment.order.ship_to_zipcode.to_s,
"PhoneNumber" => shipment.order.ship_to_phonenumber.to_s
}
items = []
shipment.m2m_line_item_shipments.each do |m2m|
items << {"SellerSKU" => m2m.vendor_sku.name.to_s, "SellerFulfillmentOrderItemId" => m2m.vendor_sku.name.to_s, "Quantity" => m2m.line_item.actual_quantity }
end
order_comment = "#{shipment.order.store.name} shipment number: " + shipment.id.to_s
opts = {:fulfillment_policy => "FillAll", :notification_email_list => [shipment.order.ship_to_email.to_s] }
created_at = shipment.order.created_at.iso8601
response = #client.create_fulfillment_order(shipment.id.to_s, shipment.id.to_s, created_at, order_comment.to_s, 'Standard', address, items, opts)
order = response.parse
logger.debug "order.inspect: #{order.inspect}"
Edit: After some more digging I found this. I tried sending item quantity as integer and string but the same error occurs:
<Error>
<Type>Sender</Type>
<Code>InvalidRequestException</Code>
<Message>Value AllQuantityZero for parameter is invalid.</Message>
</Error>
After more searching, I found my answer. Turns out this error means that the SKU is out of stock. Great error message amazon!
Source:
https://sellercentral.amazon.com/forums/message.jspa?messageID=2745103
***** RESPONSE: Net::HTTPOK -> {"status":"Success","primary_language":"notsure","PortalID":"1017","newContact":{"attributes":{"type":"Contact","url":"/services/data/v31.0/sobjects/Contact/003f000000goEpIAAU"},"Primary_Language_Master__c":"notsure","npe01__Preferred_Email__c":"Personal","Country_of_Birth_Master__c":"argentina","npe01__HomeEmail__c":"john.smith1228+689#gmail.com","RecordTypeId":"012i0000000Ng8uAAC","Portal_ID__c":1017,"FirstName":"John","Id":"003f000000goEpIAAU","LastName":"Smith", "High_School_Graduation_Year__c":"2007"},"message":"Create was created successfully.","lastname":"Smith","high_school_graduation_year":2007,"firstname":"John","email":"john.smith1228+689#gmail.com","country_of_residence":"argentina","ContactID":"003f000000goEpIAAU"}
The above is a response getting returned after I use the databasedotcom gem to interact with salesforce. I am trying to collect the contactid into my users table after a successfuly response.
Below is the method that I am pushing with
def salesforce_add_contact
client = Databasedotcom::Client.new("config/databasedotcom.yml")
client.authenticate(:username => "secret", :password => "secret" )
params = { :PortalID => current_user.id.to_s,
:firstname => current_user.first_name,
:lastname => current_user.last_name,
:email => current_user.email,
:country_of_residence => current_user.country_of_residence,
:primary_language => current_user.primary_language,
:high_school_graduation_year => current_user.high_school_graduation_year}
params = ActiveSupport::JSON.encode(params)
path = "/services/apexrest/v2/portalAccount"
result = client.http_post(path, params)
result = ActiveSupport::JSON.decode(result.body)
puts result.body #just added
if (response['status'] == "Success") #this didn't work
current_user.sfdc_contact_id = response['ContactId']
current_user.sfdc_contact_id.save
end
end
I am not totally understanding the syntax from the response and what kind of data structure is getting returned either....
I am trying to collect this "ContactID":"003f000000goEpIAAU"
Updated
I am getting NoMethodError (undefined methodbody' for #):`
when I do a puts result.body so I guess its not reading it correctly.
It looks you misnamed the variable that contains the decoded JSON response. You have:
result = ActiveSupport::JSON.decode(result.body)
Which should be:
response = ActiveSupport::JSON.decode(result.body)
I am new to WSDL.
Code (I have added in the view directly - for test): (Page: http://localhost:3000/ccapis )
require 'savon'
client = Savon::Client.new(wsdl: "http://localhost:3000/ccapis/wsdl")
result = client.call(:fetch_prizes, message: { :gl_id => "123456789" })
result.to_hash
And in the controller:
soap_action "fetch_prizes",
:args => { :gl_id => :string },
:return => [:array]
def fetch_prizes
glnumber = params[:gl_id ]
prize = Prize.where(:gl_id => glnumber)
prize_to_show = []
a_hash = {}
prize.each do |p|
a_hash = { :prize => p.prize.to_s, :score => p.score.to_s, :date => p.round_date.to_s }
prize_to_show.push a_hash
a_hash = nil
end
render :soap => prize_to_show
end
When I try and run this in the Console all are good and I can see the result.to_hash but when I go to http://0.0.0.0:3000/ccapis I get the error that I mentioned above.
Explanation of what I am trying to achieve:
I need to supply a WSDL for a client which fetches all the prizes based on a score.
If My approach is wrong please direct me to a document so I can have a read and get a better understanding. Thanks again.
I have a method that return a Hash and then I write the entries of hash in xml file. Iwant to convert this Hash to an object to store the entry and then write it to xml file...
My current code is like this
def entry(city)
{
:loc => ActionController::Integration::Session.new.url_for(:controller => 'cities', :action => 'show', :city_name => city.name, :host => #country_host.value),
:changefreq => 0.8,
:priority => 'monthly',
:lastmod => city.updated_at
}
end
The write_entry method is inside my writer class that writes this entry to xml file
def write_entry(entry)
url = Nokogiri::XML::Node.new( "url" , #xml_document )
%w{loc changefreq priority lastmod}.each do |node|
url << Nokogiri::XML::Node.new( node, #xml_document ).tap do |n|
n.content = entry[ node.to_sym ]
end
end
url.to_xml
end
Thanks
I might be way off here, but it seems like what you're trying to do is something like this:
First, figure out what makes sense as a class name for your new object. I'm going with Entry, because that's the name of your method:
class Entry
end
Then take all the "properties" of your hash and make them reader methods on the object:
class Entry
attr_reader :loc, :action, :changefreq, :priority, :lastmod
end
Next you need to decide how this object will be initialized. It seems like you will need both the city and #country_host for this:
class Entry
attr_reader :loc, :action, :changefreq, :priority, :last mod
def initialize(city, country_host_value)
#loc = ActionController::Integration::Session.new.url_for(:controller => 'cities', :action => 'show', :city_name => city.name, :host => country_host_value)
#changefreq = 0.8 # might actually want to just make this a constant
#priority = 'monthly' # another constant here???
#lastmod = city.updated_at
end
end
Finally add your XML builder method to the class:
class Entry
attr_reader :loc, :action, :changefreq, :priority, :last mod
def initialize(city, country_host_value)
#loc = ActionController::Integration::Session.new.url_for(:controller => 'cities', :action => 'show', :city_name => city.name, :host => country_host_value)
#changefreq = 0.8 # might actually want to just make this a constant
#priority = 'monthly' # another constant here???
#lastmod = city.updated_at
end
def write_entry_to_xml(xml_document)
url = Nokogiri::XML::Node.new( "url" , xml_document )
%w{loc changefreq priority lastmod}.each do |node|
url << Nokogiri::XML::Node.new( node, xml_document ).tap do |n|
n.content = send(node)
end
end
url.to_xml
end
end
Now that your hash has been refactored, you can update your other class(es) to use the new object:
class WhateverClassThisIs
def entry(city)
Entry.new(city, #country_host.value)
end
end
It's not clear how the XML writer method is being called, but you would need to update that as well to use the new write_entry_to_xml method, passing in the xml document as an argument.