fedspendingtransparency/usaspending-api

View on GitHub
usaspending_api/accounts/views/financial_spending.py

Summary

Maintainability
A
3 hrs
Test Coverage
A
90%
from django.db.models import F, Sum, Case, TextField, Value, When
from usaspending_api.accounts.serializers import (
    ObjectClassFinancialSpendingSerializer,
    MinorObjectClassFinancialSpendingSerializer,
)
from usaspending_api.common.exceptions import InvalidParameterException
from usaspending_api.common.views import CachedDetailViewSet
from usaspending_api.financial_activities.models import FinancialAccountsByProgramActivityObjectClass
from usaspending_api.references.models import Agency
from usaspending_api.submissions.models import SubmissionAttributes


class ObjectClassFinancialSpendingViewSet(CachedDetailViewSet):
    """
    Returns financial spending data by object class for the latest quarter based on the given fiscal year.
    """

    endpoint_doc = "usaspending_api/api_contracts/contracts/v2/financial_spending/major_object_class.md"

    serializer_class = ObjectClassFinancialSpendingSerializer

    def get_queryset(self):
        # retrieve post request payload
        json_request = self.request.query_params

        # retrieve fiscal_year & agency_id from request
        fiscal_year = json_request.get("fiscal_year", None)
        funding_agency_id = json_request.get("funding_agency_id", None)

        # required query parameters were not provided
        if not (fiscal_year and funding_agency_id):
            raise InvalidParameterException(
                "Missing one or more required query parameters: fiscal_year, funding_agency_id"
            )

        toptier_agency = Agency.objects.filter(id=funding_agency_id).first()
        if toptier_agency is None:
            return FinancialAccountsByProgramActivityObjectClass.objects.none()
        toptier_agency = toptier_agency.toptier_agency

        submission_queryset = SubmissionAttributes.objects.all()
        submission_queryset = (
            submission_queryset.filter(toptier_code=toptier_agency.toptier_code, reporting_fiscal_year=fiscal_year)
            .order_by("-reporting_fiscal_year", "-reporting_fiscal_quarter")
            .annotate(fiscal_year=F("reporting_fiscal_year"), fiscal_quarter=F("reporting_fiscal_quarter"))
        )
        submission = submission_queryset.first()

        if submission is None:
            return FinancialAccountsByProgramActivityObjectClass.objects.none()
        active_fiscal_year = submission.reporting_fiscal_year
        active_fiscal_quarter = submission.fiscal_quarter

        # Special case: major object class name for class 00 should be reported
        # as Unknown Object Type, overriding actual value in database
        queryset = (
            FinancialAccountsByProgramActivityObjectClass.objects.filter(
                submission__reporting_fiscal_year=active_fiscal_year,
                submission__reporting_fiscal_quarter=active_fiscal_quarter,
                treasury_account__funding_toptier_agency=toptier_agency,
                submission__is_final_balances_for_fy=True,
            )
            .annotate(
                major_object_class_name=Case(
                    When(object_class__major_object_class="00", then=Value("Unknown Object Type")),
                    default="object_class__major_object_class_name",
                    output_field=TextField(),
                ),
                major_object_class_code=F("object_class__major_object_class"),
            )
            .values("major_object_class_name", "major_object_class_code")
            .annotate(obligated_amount=Sum("obligations_incurred_by_program_object_class_cpe"))
            .order_by("major_object_class_code")
        )

        return queryset


class MinorObjectClassFinancialSpendingViewSet(CachedDetailViewSet):
    """
    Returns financial spending data by object class for the latest quarter in the given fiscal year.
    """

    endpoint_doc = "usaspending_api/api_contracts/contracts/v2/financial_spending/object_class.md"

    serializer_class = MinorObjectClassFinancialSpendingSerializer

    def get_queryset(self):
        # retrieve post request payload
        json_request = self.request.query_params

        # retrieve fiscal_year & agency_id from request
        fiscal_year = json_request.get("fiscal_year", None)
        funding_agency_id = json_request.get("funding_agency_id", None)
        major_object_class_code = json_request.get("major_object_class_code", None)

        # required query parameters were not provided
        if not (fiscal_year and funding_agency_id and major_object_class_code):
            raise InvalidParameterException(
                "Missing one or more required query parameters: fiscal_year, funding_agency_id, major_object_class_code"
            )

        toptier_agency = Agency.objects.filter(id=funding_agency_id).first()
        if toptier_agency is None:
            return FinancialAccountsByProgramActivityObjectClass.objects.none()
        toptier_agency = toptier_agency.toptier_agency

        submission_queryset = SubmissionAttributes.objects.all()
        submission_queryset = (
            submission_queryset.filter(toptier_code=toptier_agency.toptier_code, reporting_fiscal_year=fiscal_year)
            .order_by("-reporting_fiscal_year", "-reporting_fiscal_quarter")
            .annotate(fiscal_year=F("reporting_fiscal_year"), fiscal_quarter=F("reporting_fiscal_quarter"))
        )
        submission = submission_queryset.first()

        if submission is None:
            return FinancialAccountsByProgramActivityObjectClass.objects.none()
        active_fiscal_year = submission.reporting_fiscal_year
        active_fiscal_quarter = submission.fiscal_quarter

        queryset = FinancialAccountsByProgramActivityObjectClass.objects.filter(
            submission__is_final_balances_for_fy=True
        )
        # get the incoming agency's toptier agency, because that's what we'll
        # need to filter on
        # (used filter() instead of get() b/c we likely don't want to raise an
        # error on a bad agency id)
        queryset = queryset.filter(
            submission__reporting_fiscal_year=active_fiscal_year,
            submission__reporting_fiscal_quarter=active_fiscal_quarter,
            treasury_account__funding_toptier_agency=toptier_agency,
            object_class__major_object_class=major_object_class_code,
        )
        queryset = queryset.annotate(
            object_class_name=F("object_class__object_class_name"), object_class_code=F("object_class__object_class")
        )
        # sum obligated_mount by object class
        queryset = queryset.values("object_class_name", "object_class_code").annotate(
            obligated_amount=Sum("obligations_incurred_by_program_object_class_cpe")
        )
        # get minor object class vars
        return queryset