Manager for Task model with Data Manager annotations. Provides: - Advanced query annotations for Data Manager - Filter and ordering support - FSM state annotation support (via TaskQuerySet) Note: Overrides the base get_queryset() to return TaskQuerySet. Also has a cust
| 771 | |
| 772 | |
| 773 | class PreparedTaskManager(models.Manager): |
| 774 | """ |
| 775 | Manager for Task model with Data Manager annotations. |
| 776 | |
| 777 | Provides: |
| 778 | - Advanced query annotations for Data Manager |
| 779 | - Filter and ordering support |
| 780 | - FSM state annotation support (via TaskQuerySet) |
| 781 | |
| 782 | Note: Overrides the base get_queryset() to return TaskQuerySet. Also has |
| 783 | a custom get_queryset(fields_for_evaluation, prepare_params, ...) method |
| 784 | for Data Manager-specific functionality. |
| 785 | """ |
| 786 | |
| 787 | @staticmethod |
| 788 | def annotate_queryset( |
| 789 | queryset, fields_for_evaluation=None, all_fields=False, excluded_fields_for_evaluation=None, request=None |
| 790 | ): |
| 791 | annotations_map = get_annotations_map() |
| 792 | # If we have dynamic control-tag level agreement columns, inject into annotation map |
| 793 | # without mutating the global map |
| 794 | if flag_set('fflag_utc_428_consensus_control_tag_agreement', user='auto'): |
| 795 | inject_path = getattr(settings, 'GET_DYNAMIC_DM_ANNOTATIONS', None) |
| 796 | if inject_path: |
| 797 | overlay_func = load_func(inject_path) |
| 798 | # Expect a dict of {field_name: function that annotates the queryset} |
| 799 | overlay_map = overlay_func(request=request, project=getattr(queryset.first(), 'project', None)) or {} |
| 800 | if isinstance(overlay_map, dict) and overlay_map: |
| 801 | # Only add overlay_map keys if they're explicitly requested in fields_for_evaluation |
| 802 | # or if all_fields=True. Don't automatically add all overlay_map keys to avoid |
| 803 | # processing all tasks when only a page is needed (e.g., in only_filtered). |
| 804 | # Merge overlay with base map for this call only (all keys available, but only used if requested) |
| 805 | annotations_map = {**annotations_map, **overlay_map} |
| 806 | # Only add overlay_map keys to fields_for_evaluation if they're explicitly requested |
| 807 | if fields_for_evaluation is not None: |
| 808 | # Only include overlay_map keys that are already in fields_for_evaluation |
| 809 | overlay_keys_in_request = [k for k in overlay_map.keys() if k in fields_for_evaluation] |
| 810 | if overlay_keys_in_request: |
| 811 | # Ensure they're in the list (they already are, but this makes it explicit) |
| 812 | fields_for_evaluation = list(set(fields_for_evaluation) | set(overlay_keys_in_request)) |
| 813 | |
| 814 | if fields_for_evaluation is None: |
| 815 | fields_for_evaluation = [] |
| 816 | |
| 817 | if excluded_fields_for_evaluation is None: |
| 818 | excluded_fields_for_evaluation = [] |
| 819 | |
| 820 | first_task = queryset.first() |
| 821 | project = None if first_task is None else first_task.project |
| 822 | |
| 823 | # db annotations applied only if we need them in ordering or filters |
| 824 | for field in annotations_map.keys(): |
| 825 | # Include field if it's explicitly requested or all_fields=True, but exclude if it's in the exclusion list |
| 826 | if (field in fields_for_evaluation or all_fields) and field not in excluded_fields_for_evaluation: |
| 827 | queryset.project = project |
| 828 | queryset.request = request |
| 829 | function = annotations_map[field] |
| 830 | queryset = function(queryset) |
no outgoing calls