pritaeas
pritaeas

Reputation: 2093

Odoo v12 API get invoice PDF

This question got me started with my C# Odoo API implementation. I have working code using CookComputing.XmlRpcV2 to retrieve a list of invoices.

What I would like to implement is the option to retrieve/download a PDF of a selected invoice. Does anybody know what I would need to get this done?

When I search, I find forum posts stating reporting doesn't work since V11, such as this one. Neither do I see it mentioned in the online documentation for V12, although there is mention of it at the bottom of the page for V10.

Update

Someone mentioned to construct an URL:

http://localhost:8069/my/invoices/1?report_type=pdf&download=true&access_token=<ACCESSTOKEN>

Where 1 is the invoice ID. Technically this works, but requires me to be logged in to the portal using the browser. Even if I can log into the portal from my C# service, I do not know where/how to retrieve the correct access token. I can see this is in GUID form. Does anybody know whether this is the same token I could retrieve from the OAuth2 REST API (which is a paid module b.t.w.)?

Upvotes: 4

Views: 3978

Answers (4)

LNF
LNF

Reputation: 709

I am currently testing a similar functionality but with stock.picking where I need delivery form downloaded from a remote Odoo instance and saved as an attachment in another instance. What I did is adding this function to stock.picking in remote Odoo.

@api.model
def sd_get_delivery_form(self, uid):
    picking = self.env['stock.picking'].sudo().search([('sd_uid', 'like', uid)], limit=1)
    if picking and picking.sale_id:
        pdf = self.env.ref('sale.action_report_saleorder').sudo().render_qweb_pdf([picking.sale_id.id])
        b64_pdf = base64.b64encode(pdf[0])
        order_pdf = b64_pdf.decode('utf-8')
        return {'file': order_pdf}
    else:
        return False

Then calling it using xmlrpc and save it as an attachment

attachment_name = "delivery_order_({})".format(self.id)
self.env['ir.attachment'].create({
    'name': attachment_name,
    'type': 'binary',
    'datas': dt['file'],
    'datas_fname': attachment_name + '.pdf',
    'store_fname': attachment_name,
    'res_model': self._name,
    'res_id': self.id,
    'mimetype': 'application/x-pdf'
})

What you can do in C# is getting the base64 and save it as PDF if you like to go in this similar way.

Upvotes: 1

Quentin THEURET
Quentin THEURET

Reputation: 1232

The simplest way is to use OdooRPC library : https://pythonhosted.org/OdooRPC/ref_report.html

Upvotes: 0

Paul von Hoesslin
Paul von Hoesslin

Reputation: 128

Correct. You can download the PDF by placing in the access_token.

This is the only way I managed to figure it out for Odoo v.12. after smashing my head against a brick wall repeatedly. My example programming language is with Python 3 though, not C#, but I'm sure you can adapt it.

odoo_url_host = "https://company.odoo.com"

The access_token can be found in the invoice's JSON response.

invoice_id = 1234
models = xmlrpcclient.ServerProxy('{}/xmlrpc/2/object'.format(odoo_url_host))
invoice = models.execute_kw(db, uid, password, "account.invoice", read, [[invoice_id]])

which, provided you get back a found invoice, you can use the response like so:

print(invoice["access_token"])

download_url = "%s/%s/my/invoices/%d?report_type=pdf&download=true&access_token=%s" % (odoo_url_host, invoice_id, invoice["access_token"])

Which if you simply want to automatically download, can be done like so:

import urllib.request

pdf_destination = "./invoices/invoice-%d.pdf" % invoice_id

urllib.request.urlretrieve(download_url, pdf_destination)

You'd need to change the way this is written for Python 2.7.

Also, make sure that you click 'share' on the invoice (within odoo) as sometimes the access_token doesn't get generated for that invoice and returns false otherwise.

Or if you'd like to seamlessly have the access_token generated, execute this before trying to get the access token:

ctx = {'active_model': 'account.invoice', 'active_id': invoice_id}
print(models.execute_kw(db, uid, password, 'portal.share', 'default_get',[{}],{'context': ctx}))

That should get you the share_link for the entire document, but all you need is the access_token to be generated. You can extract the access_token from the share_link value in the JSON response, if you'd like to do it that way. Anyway :) Happy coding.

Upvotes: 5

CZoellner
CZoellner

Reputation: 14801

I would try to use /xmlrpc/2/object with model ir.actions.report and method render_qweb_pdf. Bear in mind that you'll need a ir.actions.report record, because render_qweb_pdf isn't a "model method" (in OOP class method).

Upvotes: 1

Related Questions