Is there a way to have a kind of virtual field on a doctype, evaluated at the time of usage

Is there a way to have a kind of virtual field on a doctype, evaluated at the time of usage

For example I am triggering a webhook which needs a bearer token calculated and populated as one of the headers

if it is possible I want to use jinja template in the headers with that evaluated value

Yeah, I think you could get it to work. For the sake of an example lets says its ‘qty * price = total’
I would make a custom field called total_amount that’s a read_only type, which won’t create a column in the DB. On the doctype you want to compute it with a property:

@property
def total_amount(self):
    return self.qty * self.price 
    # with default value of zero
    # return self.qty * self.price if self.qty and self.price else 0

In JS you’d want to do something similar to actually compute it. The @property on the python side won’t translate to the UI automatically.

2 Likes

Thanks for the answer.

sorry I am new to Frappe, does this needs to be added in controller for that doc type and can be accessed with doctype.total_amount ?

Yes, that’s where you want it. It should be a method of PurchaseOrderItem for example, but whatever doctype you’re working on.

Thank you again :pray:t3:. Will try it out

Thanks for the hint.
How would I do this in JS to have a virtual field in the List View or Form View?

1 Like

Form should be handled more like the case above. In the form view, the document goes through Frappe’s frappe.get_doc load abstraction so you have a simpler path.
In the list view, it uses the frappe.get_list method, which just returns the results of the fields. You might be able to achieve this (I haven’t tried) by adding your ‘virtual field’ to have ‘in list view’ and then using a formatter to do the computation. You probably have to add the fields you’re basing the computation on to the add_fields key. Docs: List

The idiomatic approach here is to calculate the value and store it. Just because you can compute these things on the fly doesn’t mean you should. Conversely, the portal API has a utility to provide your own listview function but that’s not part of the design in the app/ERPNext.

1 Like

Thanks for trying to help me out, but I’m just starting with frappe and your explanations are too advanced for poor little me.

What I tried so far:
I created a DocType called “Virtual Field” with these 3 fields: Article(Data), Price(Int), Amount(Int).
I would like to create a List View that shows the Columns Article, Price, Amount and Total.
As expected Total will be computed Price * Amount.
I also created a ClientScript:

frappe.listview_settings['Virtual Field'] = {
    hide_name_column: true,
    add_fields: ['total'], // Q: How should frappe know the column label of this field?
	formatters: {
        total(val) {
            return "See me!"; // Q: I get only passed the value of one field, how do I access the other fields?
        }
    }
}

This of course doesn’t work, it just shows my skill level and what I gleaned from your answer. It would be great if you could help me to work this out.

Did you manage to figure this out. I’m trying to do similar thing by having a calculated total row (qty * price) or for example taxes (total * taxe_rate) in a list view.

Hi, there. I gave up on this because I could not find a solution.

FWIW, Frappe will provide UI-based support for virtual properties/fields in v14.

https://github.com/frappe/frappe/pull/14593

1 Like