Repository: frappe/frappe
Pull request: fix: virtual fields in child tables not displaying
fixes #20526

backport version-14-hotfix


Problem statement:
Virtual fields display broken in child tables
## Description of the issue

Virtual fields content is not displayed anymore in child grids.
The cell remains blank instead of showing the virtual field result.

## Context information (for bug reports)

**Output of `bench version`**
```
frappe 14.30.0
```
(custom app)

## Steps to reproduce the issue

1. Create a field as virtual in a child doctype
2. Implement the backend code thru a @property
3. Add a grid to your doctype to display the child doctype

### Observed result

The backend code is well executed, but the result is not displayed client-side in the corresponding column of the child grid (even though the user has full permissions to view it)

### Expected result

The result of the virtual field computation should be displayed.

## Solution

in file: 

```
/apps/frappe/frappe/model/base_document.py
```

in method: 

```
get_valid_dict()
```

this line:

```
permitted_fields = get_permitted_fields(doctype=self.doctype)
```

should be replaced by:

```
if parent_doc := getattr(self, "parent_doc", None):
    permitted_fields = get_permitted_fields(doctype=self.doctype, parenttype=parent_doc.doctype)
else:
    permitted_fields = get_permitted_fields(doctype=self.doctype)
```

Hints from issue discussion:
Bug introduced with PR #20244

Commit message: fix: virtual fields in child tables

Patch to review:
diff --git a/frappe/model/base_document.py b/frappe/model/base_document.py
index 93fddcf68639..5bb034f5df3c 100644
--- a/frappe/model/base_document.py
+++ b/frappe/model/base_document.py
@@ -304,7 +304,10 @@ def get_valid_dict(
 		self, sanitize=True, convert_dates_to_str=False, ignore_nulls=False, ignore_virtual=False
 	) -> dict:
 		d = _dict()
-		permitted_fields = get_permitted_fields(doctype=self.doctype)
+		if parent_doc := getattr(self, "parent_doc", None):
+			permitted_fields = get_permitted_fields(doctype=self.doctype, parenttype=parent_doc.doctype)
+		else:
+			permitted_fields = get_permitted_fields(doctype=self.doctype)
 
 		for fieldname in self.meta.get_valid_columns():
 			field_value = getattr(self, fieldname, None)


Code review comments:
diff_hunk: @@ -304,7 +304,10 @@ def get_valid_dict(
 		self, sanitize=True, convert_dates_to_str=False, ignore_nulls=False, ignore_virtual=False
 	) -> dict:
 		d = _dict()
-		permitted_fields = get_permitted_fields(doctype=self.doctype)
+		if parent_doc := getattr(self, "parent_doc", None):
+			permitted_fields = get_permitted_fields(doctype=self.doctype, parenttype=parent_doc.doctype)
+		else:
+			permitted_fields = get_permitted_fields(doctype=self.doctype)
path: frappe/model/base_document.py
text: @user1:
```suggestion
		permitted_fields = get_permitted_fields(doctype=self.doctype, parenttype=getattr(self, "parenttype", None))
```


This should be equivalent? 

@author:
Way more elegant. Thanks :)