Require - Doctype's public accessible print pdf url

Hi,
I need to share public sharable url for my doctype (example: Sales Invoice pdf file with my Print Format). I could get some hashed url (https://somewebsitename.com/Sales%20Invoice/SINV-21-00342?format=My%20Custom%20Sales%20Invoice&key=e4ff0c02ba020a586aaca34b96756cc64ddcefbc42ac98560afb0673)in email notification but I want to achieve the same in SMS notification text that can be shared with my Customers or Users.

Right now, {{ doc.geturl() }} in my SMS Notification template is giving output something like this https://somewebsitename.com/app/Sales%20Invoice/SINV-21-00342 which has restricted access

Thanks in advance.
Regards,
Vinod Kumar K

That is what I use :

Exemple for delivery note

{{frappe.get_url()}}/delivery_note/{{doc.name}}?key={{frappe.get_doc(doc.doctype, doc.name).get_signature()}}

1 Like

Thanks Frederic. I ll give it a try

@VinodKumarkolli just give print permissions to Guest

Be careful with this. It is not a good solution in most situations, as guest users will be able to view all invoices from easily guessable URLs. @FredericVerville’s solution is much more secure.

@peterg not if you are good at coding and you can encrypt the name

I don’t follow you. These are URLs, derived from naming series. You can’t encrypt them if you want them to work.

Giving guests print permission is a bad practice.

1 Like

@peterg you can do anything you want if you are good enough at coding . in my case I encrypted the sales invoice name to something like “mlsdkfiekjsbnwbczidqsjocvpoxcqnaizdlqsdazeqlskjlazelkjakjqslqjd=” using python encrypt and changed the download pdf function to decrypt the code before generating pdf. this way you cant guess any other sales invoice name .

This is not a good practice or good advice.

2 Likes

I implemented this by creating a custom field link_code on the doctype you need to print.

create a hook for an after_insert on the doctype to populate the link code

def create_payment_link_code(doc, method=None):
    doc.link_code = frappe.generate_hash(length=56) + doc.name.split("-")[-1]
    doc.save()

I did not take any chances on duplicate link_codes being created I concated the doc name series to ensure their uniqueness.

I then create the following whitelisted method. Note the ignore_permission flag to ensure that no permissions are checked.

@frappe.whitelist(allow_guest=True)
def download_receipt(ref):
    payment_name = frappe.get_all("Payment Entry", filters={"link_code": ref}, fields=["name"])[0]
    doc = frappe.get_doc("Payment Entry", payment_name.name)
    doc.flags.ignore_permissions = 1
    
    with print_language(None):
        pdf_file = frappe.get_print(
            "Payment Entry", doc.name,  doc=doc, as_pdf=True, letterhead=None, no_letterhead=1
        )

    frappe.local.response.filename = "{name}.pdf".format(
        name=doc.name.replace(" ", "-").replace("/", "-")
    )
    frappe.local.response.filecontent = pdf_file
    frappe.local.response.type = "pdf"

Call the method with the unique link_code to generate the pdf