Delete Invoice from Xero - ruby-on-rails

I'm trying to delete an invoice from Xero by updating its status to "DELETED". Following the xeroizer github page I have tried the following:
xero = XeroApp.find_by(business_id: 270);
invoice = xero.find_invoice_by_ref(372).first
delete_invoice = xero.xero_client.Invoice.build(id: invoice.id, status: 'DELETED')
delete_invoice.save #=> false
delete_invoice.status #=> "AUTHORISED"
Unfortunately this doesn't update the invoice status. I thought that maybe removing the corresponding payment may help but it didn't. Incidentally I used a similar approach for removing the payment as above which did work.
Response to delete_invoice.save is:
XeroGateway Request: GET /api.xro/2.0/Invoices/09b354ba-c659-4aac-b353-7d56cb52c2d6?unitdp=4
XeroGateway Response (200)
/api.xro/2.0/Invoices/09b354ba-c659-4aac-b353-7d56cb52c2d6?unitdp=4
== Response Body
<Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance">
<Id>3033fc56-2eed-446c-a16b-1c0a3678f6cf</Id>
<Status>OK</Status>
<ProviderName>My-App</ProviderName>
<DateTimeUTC>2022-02-24T13:40:46.7218944Z</DateTimeUTC>
<Invoices>
<Invoice>
<Contact>
<ContactID>0bb81c84-22a0-40fc-a12b-322646752710</ContactID>
<ContactStatus>ACTIVE</ContactStatus>
<Name>Sagar Pandya</Name>
<Addresses>
<Address>
<AddressType>STREET</AddressType>
</Address>
<Address>
<AddressType>POBOX</AddressType>
<AddressLine1>123 High Road</AddressLine1>
<City>London</City>
<PostalCode>SW1 8RE</PostalCode>
<Country>United Kingdom</Country>
</Address>
</Addresses>
<Phones>
<Phone>
<PhoneType>DEFAULT</PhoneType>
<PhoneNumber>07123456789</PhoneNumber>
</Phone>
<Phone>
<PhoneType>DDI</PhoneType>
</Phone>
<Phone>
<PhoneType>FAX</PhoneType>
</Phone>
<Phone>
<PhoneType>MOBILE</PhoneType>
</Phone>
</Phones>
<UpdatedDateUTC>2022-02-08T20:01:08.327</UpdatedDateUTC>
<IsSupplier>false</IsSupplier>
<IsCustomer>true</IsCustomer>
</Contact>
<Date>2022-02-24T00:00:00</Date>
<DueDate>2022-02-24T00:00:00</DueDate>
<BrandingThemeID>5d4dd402-c851-497e-aae1-9ff265c0d15a</BrandingThemeID>
<Status>AUTHORISED</Status>
<LineAmountTypes>Exclusive</LineAmountTypes>
<LineItems>
<LineItem>
<ItemCode>FOOTYT</ItemCode>
<Description>Football T-Shirt</Description>
<UnitAmount>100.0000</UnitAmount>
<TaxType>NONE</TaxType>
<TaxAmount>0.00</TaxAmount>
<LineAmount>100.00</LineAmount>
<AccountCode>200</AccountCode>
<Item>
<ItemID>0ad76998-051d-4031-9f97-fba6b9bb255e</ItemID>
<Code>FOOTYT</Code>
</Item>
<Quantity>1.0000</Quantity>
<LineItemID>497fc08c-3571-49cb-bcd7-6a28533f9d34</LineItemID>
</LineItem>
</LineItems>
<SubTotal>100.00</SubTotal>
<TotalTax>0.00</TotalTax>
<Total>100.00</Total>
<UpdatedDateUTC>2022-02-24T12:26:13.317</UpdatedDateUTC>
<CurrencyCode>GBP</CurrencyCode>
<Type>ACCREC</Type>
<InvoiceID>09b354ba-c659-4aac-b353-7d56cb52c2d6</InvoiceID>
<InvoiceNumber>INV-0073</InvoiceNumber>
<Reference>372</Reference>
<AmountDue>100.00</AmountDue>
<AmountPaid>0.00</AmountPaid>
<SentToContact>false</SentToContact>
<CurrencyRate>1.0000000000</CurrencyRate>
<HasAttachments>false</HasAttachments>
<HasErrors>false</HasErrors>
</Invoice>
</Invoices>
</Response>
== End Response Body
=> false

Use the methods outlined in the api here:
https://github.com/waynerobinson/xeroizer/blob/master/lib/xeroizer/models/invoice.rb
For this question: After retrieving the invoice use invoice.void!.

Related

Nokogiri : NoMethodError (undefined method `inner_html' for nil:NilClass)

I'm trying to parse a simple XML data with nokogiri.
this is my XML:
POST /.... HTTP/1.1
Host: ....
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://...."
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="...." xmlns:xsd="...." xmlns:soap="....">
<soap:Body>
<WS_QueryOnSec xmlns="......">
<type>string</type>
<ID>string</ID>
</WS_QueryOnSec>
</soap:Body>
</soap:Envelope>
and this is my simle request:
require "nokogiri"
#doc = Nokogiri::XML(request.body.read)
#something = #doc.at('type').inner_html
But Nokogiri can not find the Type or ID node.
When I change the data into this every thing works fine:
<soap:Body>
<type>string</type>
<ID>string</ID>
</soap:Body>
It seems the problem is the raw text above the data and the nods with xmlns or the other attributes!
What do you recommend to resolve this ?
The first "XML" isn't XML. It's text that contains XML. Remove the header information down to the blank line and try it again.
I think it'd help you to read the XML spec or to read some tutorials about creating XML which will help you understand how it's defined. XML is a tight specification and doesn't allow any deviation. The syntax is pretty flexible, but you have to play by its rules.
Consider these examples:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
foo
<root>
<node />
</root>
EOT
doc.errors # => [#<Nokogiri::XML::SyntaxError: Start tag expected, '<' not found>]
Removing the text, which is outside the root tag results in a proper parse:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<root>
<node />
</root>
EOT
doc.errors # => []
<root> isn't neccesarily the name of the "root" node, it's just the outermost tag:
doc = Nokogiri::XML(<<EOT)
<foo>
<node />
</foo>
EOT
doc.errors # => []
and still results in a valid DOM/internal representation of the document:
puts doc.to_html
# >> <foo>
# >> <node></node>
# >> </foo>
Your XML sample is using namespaces, which complicate matters somewhat. The Nokogiri documentation talks about how to deal with them, so you'll want to understand that part of parsing XML because you'll encounter it again. Here's the easy way of working with them:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<?xml version="1.0" encoding="utf-8"?>
<Envelope xmlns:xsi="...." xmlns:xsd="...." xmlns:soap="....">
<Body>
<WS_QueryOnSec xmlns="......">
<type>string</type>
<ID>string</ID>
</WS_QueryOnSec>
</Body>
</Envelope>
EOT
namespaces = doc.collect_namespaces
doc.at('type', namespaces).text # => "string"

Generating iTunes XML nodes in RSS feed using Ruby/Rails

Q: How do I generate the XML nodes specific to iTunes using Ruby/Rails?
Trying to generate iTunes XML feed, e.g. (based off example):
xml.instruct! :xml, :version => "1.0"
xml.rss(:version => "2.0") do
xml.channel do
xml.title "Your Blog Title"
xml.description "A blog about software and chocolate"
xml.link posts_url
#posts.each do |post|
xml.item do
xml.title post.title
xml.description "Temporary post description"
xml.pubDate post.created_at.to_s(:rfc822)
xml.link post_url(post)
xml.guid post_url(post)
end
end
end
end
Which happily generates something like:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Your Blog Title</title>
<description>A blog about software and chocolate</description>
<link>https://pubweb-thedanielmay.c9.io/sermons</link>
<item>
... omitted ...
</item>
</channel>
</rss>
But looks like I need to generate iTunes-specific XML nodes (as per Working With iTunes, e.g.)
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0"> <-- *
<channel>
<title>Your Blog Title </title>
... omitted ...
<itunes:subtitle>A program about everything</itunes:subtitle> <-- *
... etc ...
Not sure how I generate the iTunes-specific nodes as they have colons in them.
Standard RSS nodes are like:
xml.item --> <item>
How do I get to generating nodes like:
<rss xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
<itunes:author>
Ah, answers as per code via Ryan Bates' awesome Railscasts RSS sample
xml.rss "xmlns:itunes" => "http://www.itunes.com/dtds/podcast-1.0.dtd", :version => "2.0"
and
xml.itunes :author, author

Rails: How can I parse an RSS file with Feedjira

I'm trying to parse an RSS file. It throws a 404 response when I do:
Feedjira::Feed.fetch_and_parse url
So I thought trying:
Feedjira::Parser::RSS.parse url
But that returns 0 entries
This is exactly what I'm trying:
<% Feedjira::Parser::RSS.parse("my url here").entries.each do |e| %>
<%= "#{e.title}" %><br />
<% end %>
The rss file is being parse with no problem with php in another web. This is the structure:
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
<channel>
<title>Title here</title>
... etc ...
<item>
<title>Title here</title>
... etc ...
</item>
<item> ... etc ... </item>
</channel>
</rss>
It's weird that Feedjira::Feed.fetch_and_parse url wasn't working for you. It's working perfectly fine for me.
Here's how I did it. I'm using Railscasts RSS feed for example purpose:
url = "http://railscasts.com/subscriptions/rZNfSBu1hH7hOwV1mjqyLw/episodes.rss"
feed = Feedjira::Feed.fetch_and_parse url
feed.entries.each do |entry|
puts entry.title
end

Read XML responses in to Rails

I have a URL in my controller that when called return an XML response. Let say, the response looks like this;
<?xml version="1.0" encoding="UTF-8"?>
<AutoCreate>
<Response>
<Status>YES</Status>
<name>JOSEPH</name>
<location>HOME</location>
</Response>
</AutoCreate>
How can i read these values status, name and location into variables in my controller and use them.
Thank you in advance.
can you try this,
response_json = Hash.from_xml(response).to_json
So heres an update for Rails 5,
If you are receiving an XML response the header will be 'application/xml'
You access the data using
#read the response and create a Hash from the XML
response = Hash.from_xml(request.body.read)
#read value from the Hash
status = response["AutoCreate"]["Response"]["Status"]
If the value of respose.body is;
<?xml version="1.0" encoding="UTF-8"?>
<AutoCreate>
<Response>
<Status>YES </Status>
<name> JOSEPH </name>
<location> HOME </location>
</Response>
</AutoCreate>
Then i think this should be fine.
require ‘active_support’
result = Hash.from_xml(response.body)
then;
result.status == "YES"
Would this work?
You can use https://github.com/alsemyonov/xommelier
feed = Xommelier::Atom::Feed.parse(open('spec/fixtures/feed.atom.xml'))
puts feed.id, feed.title, feed.updated
feed.entries do |entry|
puts feed.id, feed.title, feed.published, feed.updated
puts feed.content || feed.summary
end

Using Webmock to fake successful ActiveMerchant response

I'm using ActiveMerchant to integrate with Authorize.net CIM. I'm in the middle of writing up automated tests, and I've begun putting into place Webmock calls so that my tests aren't actually hitting Authorize.net each time that they run.
I've created XML files from the responses of raw request data, and for the most part, it's working well. However, when I mock up a successful response, ActiveMerchant for some reason still tells me that Response.success? is not true.
My function
if self.cim_customer_profile_id.nil?
ActiveMerchant::Billing::Base.mode = :test
customer_profile_information = {
:profile => {
:merchant_customer_id => self.customer.username.first(20),
:email => self.customer.email
}
}
gateway = ActiveMerchant::Billing::AuthorizeNetCimGateway.new(
:login => AUTHORIZE_NET_API_LOGIN_ID,
:password => AUTHORIZE_NET_API_TRANSACTION_KEY
)
response = gateway.create_customer_profile(customer_profile_information)
if response.success?
self.cim_customer_profile_id = response.authorization
else
raise StandardError, response.message
end
end
And then my stubbed response is:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
<?xml version="1.0" encoding="utf-8"?>
<createCustomerProfileResponse xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns='AnetApi/xml/v1/schema/AnetApiSchema.xsd'>
<messages>
<resultCode>
Ok
</resultCode>
<message>
<code>
I00001
</code>
<text>
Successful.
</text>
</message>
</messages>
<customerProfileId>10793616</customerProfileId>
<customerPaymentProfileIdList/>
<customerShippingAddressIdList/>
<validationDirectResponseList/>
</createCustomerProfileResponse>
Is there any reason why ActiveMerchant won't function with a successful, stubbed, request? Or am I missing something that ActiveMerchant requires in order to register that the response is actually successful?
Ah, I'm so dumb. I added new lines after all of my XML tags for readability, but they're interfering with how ActiveMerchant parses and evaluates the response.
So the correct XML response mock would be:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
<?xml version="1.0" encoding="utf-8"?>
<createCustomerProfileResponse xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns='AnetApi/xml/v1/schema/AnetApiSchema.xsd'>
<messages>
<resultCode>Ok</resultCode>
<message>
<code>I00001</code>
<text>Successful.</text>
</message>
</messages>
<customerProfileId>10793616</customerProfileId>
<customerPaymentProfileIdList/>
<customerShippingAddressIdList/>
<validationDirectResponseList/>
</createCustomerProfileResponse>

Resources