Skip to content
Snippets Groups Projects
views.py 37.3 KiB
Newer Older
import uuid
Matt's avatar
Matt committed
from typing import Optional
Matt's avatar
Matt committed
from django.core.exceptions import ValidationError, PermissionDenied
from django.contrib.contenttypes.models import ContentType
Matt's avatar
Matt committed
from django.shortcuts import get_object_or_404
Jerome Mariette's avatar
Jerome Mariette committed
from django.http import Http404

from django.conf import settings
import jsonschema
from rest_framework.decorators import api_view, permission_classes
from rest_framework.exceptions import ValidationError
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status

from backend.carbon.utils import (
    get_ghgi_consumption_data,
    serialize_ghgi_with_consumptions,
from ..utils import entity_filter, entity_get

from .models import (
    GHGI,
    Building,
    Electricity,
    Water,
    Heating,
    Refrigerant,
    SelfConsumption,
    Vehicle,
    VehicleConsumption,
    SurveyAnswer,
    CommuteSection,
    Meal,
    Travel,
    TravelSection,
    TravelNames,
    ComputerDevice,
    Purchase,
    ResearchActivity,
)
from .serializers import (
    GHGISerializer,
    BuildingSerializer,
    BuildingWCSerializer,
    VehicleSerializer,
    VehicleWCSerializer,
    CommuteSerializer,
    FoodSerializer,
    TravelSerializer,
    ComputerDeviceSerializer,
    PurchaseSerializer,
    ResearchActivitySerializer,
    VehicleConsumptionSerializer,
    ElectricitySerializer,
    RefrigerantSerializer,
    SelfConsumptionSerializer,
    WaterSerializer,
    HeatingSerializer,
from .factory import ghgi_filter
Matt's avatar
Matt committed
from ..core.models import (
    Tag,
    TagCategory,
    TaggedItem,
    Laboratory,
    boundary_update_or_create,
)
from ..scenario.factory import scenario_filter
from ..users.models import L1P5User
Jérôme Mariette's avatar
Jérôme Mariette committed

from ..core.serializers import TagCategorySerializer
Matt's avatar
Matt committed


def owns_ghgi(
    data_key: Optional[str] = "id",
    model_key: Optional[str] = "id",
    allow_super_user: Optional[bool] = False,
):
Matt's avatar
Matt committed
    """Decorates function to ensure the user owns the ghgi

    Args:

        data_key: where to look in the request.data to find
            the ghgi identifier (e.g id, ghgi_id, uuid)
        model_key: mapping of data_key in the GHGI model (e.g id, uuid)
    """
Matt's avatar
Matt committed
    def _owns_ghgi(f):
        def wrapped(request, *args, **kwargs):
Corentin's avatar
Corentin committed
            if request.method == "GET":
                identifier = int(request.query_params.get(data_key))
            else:
                identifier = request.data[data_key]
Matt's avatar
Matt committed
            kwds = {model_key: identifier}
            ghgi = get_object_or_404(GHGI, **kwds)
            if ghgi.owner != request.user:
                if allow_super_user:
Jerome Mariette's avatar
Jerome Mariette committed
                    if not L1P5User.objects.get(email=request.user).is_superuser:
                        raise PermissionDenied()
Jerome Mariette's avatar
Jerome Mariette committed
                    raise PermissionDenied()
Matt's avatar
Matt committed
            return f(request, ghgi, *args, **kwargs)
Matt's avatar
Matt committed
        return wrapped
Matt's avatar
Matt committed
    return _owns_ghgi

def validate_synthesis(synthesis):
    try:
        jsonschema.validate(synthesis, GHGI.SYNTHESIS_SCHEMA)
    except jsonschema.ValidationError as e:
        # level-up the exception
        # in views this will end up with a status code of 400 (Bad Request)
        raise ValidationError(e.message)
def validate_submitted(submitted):
    try:
        jsonschema.validate(submitted, GHGI.SUBMITTED_SCHEMA)
    except jsonschema.ValidationError as e:
        # level-up the exception
        # in views this will end up with a status code of 400 (Bad Request)
        raise ValidationError(e.message)
Matt's avatar
Matt committed

def validate_uuid(cuuid):
    try:
        uuid.UUID(cuuid)
        return True
    except ValueError:
        return False

Jerome Mariette's avatar
Jerome Mariette committed
@permission_classes([])
def get_counts(request):
    from ..transition.utils import get_counts as transition_get_counts
Matt's avatar
Matt committed

    response = Response(
        {
            "transition": transition_get_counts(),
            "nGHGI": ghgi_filter().count(),
            "nScenario": scenario_filter().count(),
Jerome Mariette's avatar
Jerome Mariette committed
            "nEntity": entity_filter(ghgis__isnull=False).distinct().count(),
        },
        status=status.HTTP_200_OK,
    )
    response["Access-Control-Allow-Origin"] = "*"
    response["Access-Control-Allow-Methods"] = "GET, OPTIONS"
    response["Access-Control-Max-Age"] = "1000"
    response["Access-Control-Allow-Headers"] = "X-Requested-With, Content-Type"
    return response
Jerome Mariette's avatar
Jerome Mariette committed
def save_ghgi(request):
Matt's avatar
Matt committed
    data = request.data.copy()
    ghgi_id = data.pop("id")
    boundary_obj = data.pop("boundary", None)
    if boundary_obj is None and ghgi_id is None:
Matt's avatar
Matt committed
        raise ValidationError("To create a ghgi the boundary must be set")

    # ghgi_id = None means that we're creating a new GHGI
    validate_submitted(data["submitted"])
Matt's avatar
Matt committed
    if ghgi_id is not None:
        # we're updating one ghgi
        # we check that the user is the owner
        ghgi = get_object_or_404(GHGI, id=ghgi_id)
        if ghgi.owner != request.user:
Matt's avatar
Matt committed
            raise PermissionDenied()

Matt's avatar
Matt committed
    # first create or update boundary (if any)
    if boundary_obj is not None:
        b = boundary_update_or_create(boundary_obj)
        data["boundary"] = b
    entity = entity_get(referent=request.user)
Jerome Mariette's avatar
Jerome Mariette committed

    if entity is None:
        raise Http404("Entity does not exist")
Matt's avatar
Matt committed

    data["entity"] = entity
    ghgi, _ = GHGI.objects.update_or_create(id=ghgi_id, defaults=data)
    serializer = GHGISerializer(ghgi)
    return Response(serializer.data, status=status.HTTP_201_CREATED)
jmariette's avatar
jmariette committed

@owns_ghgi(data_key="ghgi_id", allow_super_user=True)
Matt's avatar
Matt committed
def delete_ghgi(request, ghgi):
    ghgi.delete()
    return Response(None, status=status.HTTP_204_NO_CONTENT)
jmariette's avatar
jmariette committed

Jerome Mariette's avatar
Jerome Mariette committed
def get_all_ghgi(request):
    if request.user.is_authenticated:
        ghgi_to_return = []
        entity = entity_get(referent_id=request.user.id)
        all_ghgi = GHGI.objects.filter(
            object_id=entity.id,
Jerome Mariette's avatar
Jerome Mariette committed
            content_type=ContentType.objects.get_for_model(entity).id,
        ).order_by("-year")
        for ghgi in all_ghgi:
            all_data = get_ghgi_consumption_data(ghgi.id)
            serializer = GHGISerializer(ghgi)
            final_ghgi = copy.deepcopy(serializer.data)
Jerome Mariette's avatar
Jerome Mariette committed
            for module in all_data.keys():
                final_ghgi[module] = copy.deepcopy(all_data[module])
            ghgi_to_return.append(final_ghgi)
Matt's avatar
Matt committed
        return Response(ghgi_to_return, status=status.HTTP_200_OK)
    return Response(None, status=status.HTTP_204_NO_CONTENT)

@api_view(["GET"])
@permission_classes([IsAuthenticated])
def get_all_ghgi_without_consumptions(request):
    """Get the GHGIs list but without their associated consumptions

    Returns:
        - None if no user isn't authenticated
            This is peculiar choice but for now this allow to use the
            application in an anonymous way
        - The list of all the GHGIs otherwise
    """
    entity = entity_get(referent_id=request.user.id)
    all_ghgi = []
    if entity is not None:
        all_ghgi = GHGI.objects.filter(
            object_id=entity.id,
            content_type=ContentType.objects.get_for_model(entity).id,
        ).order_by("-year")
    serializer = GHGISerializer(all_ghgi, many=True)
    return Response(serializer.data, status=status.HTTP_200_OK)


@api_view(["POST"])
Jerome Mariette's avatar
Jerome Mariette committed
def get_ghgis_consumptions(request):
Jérôme Mariette's avatar
Jérôme Mariette committed
    if request.user.is_authenticated:
        if L1P5User.objects.get(email=request.user).is_superuser:
            module = request.data["module"]
            ghgi_to_return = []
            all_ghgi = GHGI.objects.filter(id__in=request.data["ghgis"])
            for ghgi in all_ghgi:
                all_data = get_ghgi_consumption_data(ghgi.id, module)
                serializer = GHGISerializer(ghgi)
                final_ghgi = copy.deepcopy(serializer.data)
                final_ghgi[module] = copy.deepcopy(all_data[module])
                ghgi_to_return.append(final_ghgi)
Matt's avatar
Matt committed
            return Response(ghgi_to_return, status=status.HTTP_200_OK)
Jérôme Mariette's avatar
Jérôme Mariette committed
        return Response(None, status=status.HTTP_204_NO_CONTENT)
    return Response(None, status=status.HTTP_204_NO_CONTENT)

def get_all_ghgi_admin(request):
    if request.user.is_authenticated:
        if L1P5User.objects.get(email=request.user).is_superuser:
            if "years" in request.data.keys():
                years = request.data.pop("years")
                all_ghgi = ghgi_filter(year__in=years)
Jerome Mariette's avatar
Jerome Mariette committed
            else:
                all_ghgi = ghgi_filter()
            serializer = GHGISerializer(all_ghgi, many=True)
            return Response(
                {
                    "ghgis": serializer.data,
                    "years": sorted(
                        list(
                            map(
                                lambda obj: obj["year"],
                                GHGI.objects.values("year").distinct(),
                            )
                        ),
                        reverse=True,
                    ),
                },
                status=status.HTTP_200_OK,
            )
        return Response(None, status=status.HTTP_204_NO_CONTENT)
    return Response(None, status=status.HTTP_204_NO_CONTENT)

Jerome Mariette's avatar
Jerome Mariette committed
def update_synthesis(request):
    if request.user.is_authenticated:
        if L1P5User.objects.get(email=request.user).is_superuser:
            validate_synthesis(request.data["synthesis"])
            ghgi_id = request.data.pop("ghgi_id")
            GHGI.objects.filter(id=ghgi_id).update(synthesis=request.data["synthesis"])
            return Response(None, status=status.HTTP_204_NO_CONTENT)
Matt's avatar
Matt committed
@owns_ghgi(data_key="ghgi_id")
def save_vehicles(request, ghgi):
    data = request.data
    validate_synthesis(data["synthesis"])
    entity = entity_get(referent_id=request.user.id)
    ghgi_consumptions = []
    for vehicle_data in data["vehicles"]:
        vehicle_id = vehicle_data.pop("id")
        consumption_data = vehicle_data.pop("consumption")
        consumption_id = consumption_data.pop("id")
        tags = vehicle_data.pop("tags")
        vehicle_data["entity"] = entity
        vehicle, created = Vehicle.objects.update_or_create(
            id=vehicle_id, defaults=vehicle_data
        )
        consumption_data["ghgi"] = ghgi
        consumption_data["vehicle"] = vehicle
        consumption, created = VehicleConsumption.objects.update_or_create(
            id=consumption_id, defaults=consumption_data
        )
        TaggedItem.objects.filter(object_id=vehicle.id).delete()
        for tag in tags:
            t = Tag.objects.get(id=tag["id"])
            TaggedItem.objects.create(content_object=vehicle, tag=t)
        ghgi_consumptions.append(consumption.id)
    # Delete consumptions no longer defined
Matt's avatar
Matt committed
    consumptions = VehicleConsumption.objects.filter(ghgi_id=ghgi.id)
    for consumption in consumptions:
        if not consumption.id in ghgi_consumptions:
            consumption.delete()
Jerome Mariette's avatar
Jerome Mariette committed
    # Delete vehicles with no consumption
    vehicles = Vehicle.objects.filter(object_id=entity.id)
    for vehicle in vehicles:
        consumptions = VehicleConsumption.objects.filter(vehicle_id=vehicle.id)
        if len(consumptions) == 0:
            vehicle.delete()
    # save vehicles intensity
    GHGI.objects.filter(id=ghgi.id).update(synthesis=data["synthesis"])
        get_ghgi_consumption_data(ghgi.id, "vehicles")["vehicles"],
        status=status.HTTP_201_CREATED,
Matt's avatar
Matt committed
@owns_ghgi(data_key="ghgi_id")
def save_computer_devices(request, ghgi):
    data = request.data
    validate_synthesis(data["synthesis"])
Matt's avatar
Matt committed
    ComputerDevice.objects.filter(ghgi_id=ghgi.id).delete()
    # ajouter les nouveaux
    for computer_device_data in data["devices"]:
        tags = computer_device_data.pop("tags")
        computer_device_data["ghgi_id"] = ghgi.id
        device = ComputerDevice.objects.create(**computer_device_data)
        for tag in tags:
            t = Tag.objects.get(id=tag["id"])
            TaggedItem.objects.create(content_object=device, tag=t)
    # save devices intensity
    GHGI.objects.filter(id=ghgi.id).update(synthesis=request.data["synthesis"])
Matt's avatar
Matt committed
    computer_devices = ComputerDevice.objects.filter(ghgi_id=ghgi.id)
Jerome Mariette's avatar
Jerome Mariette committed
    serializer = ComputerDeviceSerializer(computer_devices, many=True)
    return Response(serializer.data, status=status.HTTP_201_CREATED)

Matt's avatar
Matt committed
@owns_ghgi(data_key="ghgi_id")
def save_purchases(request, ghgi):
    data = request.data
    validate_synthesis(data["synthesis"])
Matt's avatar
Matt committed

    Purchase.objects.filter(ghgi_id=ghgi.id).delete()
Jerome Mariette's avatar
Jerome Mariette committed
    # ajouter les nouveaux
    for purchase_data in data["purchases"]:
        tags = purchase_data.pop("tags")
        purchase_data["ghgi_id"] = ghgi.id
Jerome Mariette's avatar
Jerome Mariette committed
        purchase = Purchase.objects.create(**purchase_data)
        for tag in tags:
            t = Tag.objects.get(id=tag["id"])
            TaggedItem.objects.create(content_object=purchase, tag=t)
    GHGI.objects.filter(id=ghgi.id).update(synthesis=data["synthesis"])
Matt's avatar
Matt committed
    purchases = Purchase.objects.filter(ghgi_id=ghgi.id)
Jerome Mariette's avatar
Jerome Mariette committed
    serializer = PurchaseSerializer(purchases, many=True)
    return Response(serializer.data, status=status.HTTP_201_CREATED)

@owns_ghgi(data_key="ghgi_id")
def save_research_activities(request, ghgi):
    data = request.data
    validate_synthesis(data["synthesis"])

    ResearchActivity.objects.filter(ghgi_id=ghgi.id).delete()
    for ractivity_data in data["ractivities"]:
        tags = ractivity_data.pop("tags")
        ractivity_data["ghgi_id"] = ghgi.id
        ractivity = ResearchActivity.objects.create(**ractivity_data)
        for tag in tags:
            t = Tag.objects.get(id=tag["id"])
            TaggedItem.objects.create(content_object=ractivity, tag=t)
    GHGI.objects.filter(id=ghgi.id).update(synthesis=request.data["synthesis"])
    ractivities = ResearchActivity.objects.filter(ghgi_id=ghgi.id)
    serializer = ResearchActivitySerializer(ractivities, many=True)
    return Response(serializer.data, status=status.HTTP_201_CREATED)

Corentin's avatar
Corentin committed
@api_view(["GET"])
def get_all_vehicles(request):
        entity = entity_get(referent_id=request.user.id)
        vehicles = Vehicle.objects.filter(
            object_id=entity.id,
Jerome Mariette's avatar
Jerome Mariette committed
            content_type=ContentType.objects.get_for_model(entity).id,
        serializer = VehicleWCSerializer(vehicles, many=True)
Matt's avatar
Matt committed
        return Response(serializer.data, status=status.HTTP_200_OK)
    except:
        return Response(None, status=status.HTTP_204_NO_CONTENT)

Matt's avatar
Matt committed
@owns_ghgi(data_key="ghgi_id")
def save_buildings(request, ghgi):
    data = request.data
    validate_synthesis(data["synthesis"])
    entity = entity_get(referent_id=request.user.id)
    all_electricities_id = []
    all_heating_ids = []
    all_refrigerants_ids = []
Jerome Mariette's avatar
Jerome Mariette committed
    all_waters_id = []
    for building_data in data["buildings"]:
        building_id = building_data.pop("id")
        building_data["entity"] = entity
        # Remove consumption data from building data to be able to create building
        electricity_data = building_data.pop("electricity")
        heatings_data = building_data.pop("heatings")
        refrigerants = building_data.pop("refrigerants")
        water_data = building_data.pop("water")
        selfconsumption_data = building_data.pop("selfConsumption")
        tags = building_data.pop("tags")
        # Create building if not exists
        building, created = Building.objects.update_or_create(
            id=building_id, defaults=building_data
        )
        electricity_id = electricity_data.pop("id")
        electricity_data["ghgi"] = ghgi
        electricity_data["building"] = building
        electricity, created = Electricity.objects.update_or_create(
            id=electricity_id, defaults=electricity_data
        )
        all_electricities_id.append(electricity.id)
        # Heatings
        for heating_data in heatings_data:
            heating_id = heating_data.pop("id")
            heating_data["ghgi"] = ghgi
            heating_data["building"] = building
            heating, created = Heating.objects.update_or_create(
                id=heating_id, defaults=heating_data
            )
            all_heating_ids.append(heating.id)
        # Refrigerant gas
        for refrigerant_data in refrigerants:
            refrigerant_id = refrigerant_data.pop("id")
            refrigerant_data["ghgi"] = ghgi
            refrigerant_data["building"] = building
            refrigerant, created = Refrigerant.objects.update_or_create(
                id=refrigerant_id, defaults=refrigerant_data
            )
Matt's avatar
Matt committed
            all_refrigerants_ids.append(refrigerant.id)
Jerome Mariette's avatar
Jerome Mariette committed
        # Water
        water_id = water_data.pop("id")
        water_data["ghgi"] = ghgi
        water_data["building"] = building
        water, created = Water.objects.update_or_create(
            id=water_id, defaults=water_data
        )
Jerome Mariette's avatar
Jerome Mariette committed
        all_waters_id.append(water.id)
        # Selfconsumption
        SelfConsumption.objects.filter(building=building, ghgi=ghgi).delete()
        selfconsumption = SelfConsumption.objects.create(
            building=building, ghgi=ghgi, total=selfconsumption_data
        # Tags
        TaggedItem.objects.filter(object_id=building.id).delete()
        for tag in tags:
            t = Tag.objects.get(id=tag["id"])
            TaggedItem.objects.create(content_object=building, tag=t)
    # Remove refrigerants and heatings that are no longer associated with the building and ghgi
    refrigerants = Refrigerant.objects.filter(ghgi=ghgi)
    for refrigerant in refrigerants:
        if not refrigerant.id in all_refrigerants_ids:
            refrigerant.delete()
    heatings = Heating.objects.filter(ghgi=ghgi)
    for heating in heatings:
        if not heating.id in all_heating_ids:
            heating.delete()
    # Remove electricity consumptions no longer present in the data being saved for the given ghgi
Matt's avatar
Matt committed
    electricities = Electricity.objects.filter(ghgi_id=ghgi.id)
    for electricity in electricities:
        if not electricity.id in all_electricities_id:
            electricity.delete()
Jerome Mariette's avatar
Jerome Mariette committed
    # Remove water consumptions no longer present in the data being saved for the given ghgi
    waters = Water.objects.filter(ghgi_id=ghgi.id)
    for water in waters:
        if not water.id in all_waters_id:
            water.delete()
    # Remove buildings no longer linked to a consumption thus to a given ghgi
    buildings = Building.objects.filter(object_id=entity.id)
    for building in buildings:
        electricity = Electricity.objects.filter(building_id=building.id)
Jerome Mariette's avatar
Jerome Mariette committed
        water = Water.objects.filter(building_id=building.id)
        heating = Heating.objects.filter(building_id=building.id)
Jerome Mariette's avatar
Jerome Mariette committed
        if len(electricity) == 0 and len(heating) == 0 and len(water) == 0:
            building.delete()
    GHGI.objects.filter(id=ghgi.id).update(synthesis=data["synthesis"])
        get_ghgi_consumption_data(ghgi.id, "buildings")["buildings"],
        status=status.HTTP_201_CREATED,
Corentin's avatar
Corentin committed
@api_view(["GET"])
Jerome Mariette's avatar
Jerome Mariette committed
def get_all_buildings(request):
        entity = entity_get(referent_id=request.user.id)
        buildings = Building.objects.filter(
            object_id=entity.id,
Jerome Mariette's avatar
Jerome Mariette committed
            content_type=ContentType.objects.get_for_model(entity).id,
        serializer = BuildingWCSerializer(buildings, many=True)
Matt's avatar
Matt committed
        return Response(serializer.data, status=status.HTTP_200_OK)
    except:
        return Response(None, status=status.HTTP_204_NO_CONTENT)
@permission_classes([])
def get_astro_alphas(request):
    import csv

    year = request.query_params.get("year")
    labID = request.query_params.get("labID")
    filename = os.path.join(
        settings.BASE_DIR, "data/researchActivities/astroAlpha_" + year + ".csv"
    )
    alphas = None
    with open(filename, newline="") as csvfile:
        for row in csv.DictReader(csvfile):
            lab_id = row.pop("lab_id")
            if lab_id == labID:
                alphas = row
    return Response(alphas, status=status.HTTP_200_OK)
@permission_classes([])
def get_astro_years(request):
    import os
    import re
    availableYears = []
    for file in os.listdir(os.path.join(settings.BASE_DIR, "data/researchActivities")):
        if file.startswith("astroAlpha"):
            availableYears.append(int(re.match("astroAlpha_(\d+).csv", file).group(1)))
    return Response(availableYears, status=status.HTTP_200_OK)
Matt's avatar
Matt committed
@owns_ghgi(data_key="ghgi_id")
def save_commutes(request, ghgi):
    data = request.data
    validate_synthesis(data["synthesis"])
    for commute_data in request.data["commutes"]:
        # update cdeleted status
        SurveyAnswer.objects.filter(id=commute_data["id"]).update(
            cdeleted=commute_data["cdeleted"]
Jerome Mariette's avatar
Jerome Mariette committed
        )
    # update intensity
    GHGI.objects.filter(id=ghgi.id).update(synthesis=data["synthesis"])
    commutes = SurveyAnswer.objects.filter(ghgi_id=ghgi.id)
Jerome Mariette's avatar
Jerome Mariette committed
    serializer = CommuteSerializer(commutes, many=True)
    return Response(serializer.data, status=status.HTTP_201_CREATED)

@owns_ghgi(data_key="ghgi_id")
def save_foods(request, ghgi):
    data = request.data
    validate_synthesis(data["synthesis"])
    for food_data in request.data["foods"]:
        # update mdeleted status
        SurveyAnswer.objects.filter(id=food_data["id"]).update(
            mdeleted=food_data["mdeleted"]
    GHGI.objects.filter(id=ghgi.id).update(synthesis=data["synthesis"])
    foods = SurveyAnswer.objects.filter(ghgi_id=ghgi.id)
    serializer = FoodSerializer(foods, many=True)
    return Response(serializer.data, status=status.HTTP_201_CREATED)

Corentin's avatar
Corentin committed
@api_view(["GET"])
@permission_classes([])
Jerome Mariette's avatar
Jerome Mariette committed
def get_ghgi_survey_info(request):
Corentin's avatar
Corentin committed
    uuid = request.query_params.get("uuid")
    if validate_uuid(uuid):
        ghgi = GHGI.objects.get(uuid=uuid)
Matt's avatar
Matt committed
        allTagCategories = ghgi.entity.tag_categories
        tagCategoriesSerializer = TagCategorySerializer(allTagCategories, many=True)
        surveyTags = list(map(lambda x: x.id, ghgi.surveyTags.all()))
        for category in tagCategoriesSerializer.data:
Jerome Mariette's avatar
Jerome Mariette committed
            ftags = [t for t in category["tags"] if t["id"] in surveyTags]
            category["tags"] = ftags
        # clean categories without tags
Jerome Mariette's avatar
Jerome Mariette committed
        categories = [c for c in tagCategoriesSerializer.data if len(c["tags"]) > 0]
        return Response(
            {
                "year": ghgi.year,
                "surveyMessage": ghgi.surveyMessage,
                "commutesActive": ghgi.commutesActive,
                "foodsActive": ghgi.foodsActive,
                "contactEmail": ghgi.entity.referent.email,
Jerome Mariette's avatar
Jerome Mariette committed
                "entityName": ghgi.entity.name,
                "surveyTagCategories": categories,
Jerome Mariette's avatar
Jerome Mariette committed
                "citySize": ghgi.entity.citySize,
            },
            status=status.HTTP_200_OK,
        )
    else:
        return Response(None, status=status.HTTP_204_NO_CONTENT)
Matt's avatar
Matt committed
@owns_ghgi(data_key="ghgi_id")
def clone_survey(request, ghgi):
    data = request.data.copy()
    surveyCloneYear = data.pop("surveyCloneYear")
Matt's avatar
Matt committed
    GHGI.objects.filter(id=ghgi.id).update(surveyCloneYear=surveyCloneYear)
    to_return = get_ghgi_consumption_data(ghgi.id, "commutes")["commutes"]
Jerome Mariette's avatar
Jerome Mariette committed
    return Response(to_return, status=status.HTTP_201_CREATED)
Jerome Mariette's avatar
Jerome Mariette committed

Matt's avatar
Matt committed
@owns_ghgi(data_key="ghgi_id")
def save_survey_config(request, ghgi):
Matt's avatar
Matt committed
    data = request.data.copy()
    surveyMessage = data.pop("surveyMessage")
    surveyTags = data.pop("surveyTags")
    ghgi = GHGI.objects.get(id=ghgi.id)
    ghgi.surveyMessage = surveyMessage
Jerome Mariette's avatar
Jerome Mariette committed
    ghgi.surveyTags.clear()
    for tag in surveyTags:
        t = Tag.objects.get(id=tag["id"])
        ghgi.surveyTags.add(t)
    ghgi.save()
    return Response({}, status=status.HTTP_201_CREATED)

@permission_classes([])
def save_survey(request):
    uuid = request.data.pop("uuid")
    survey_data = request.data.pop("survey")
    sections_data = survey_data.pop("sections")
    meals_data = survey_data.pop("meals")
    tags = survey_data.pop("tags")
Jerome Mariette's avatar
Jerome Mariette committed
    ghgi = GHGI.objects.get(uuid=uuid)
    # add the new survey result

    # FIXME(msimonin): validate position
    survey = SurveyAnswer.objects.create(ghgi_id=ghgi.id, **survey_data)
    SurveyAnswer.objects.filter(id=survey.id).update(seqID=survey.id)
Jerome Mariette's avatar
Jerome Mariette committed
    for section_data in sections_data:
Jerome Mariette's avatar
Jerome Mariette committed
        CommuteSection.objects.create(survey_id=survey.id, **section_data)
Jerome Mariette's avatar
Jerome Mariette committed
    for meal_data in meals_data:
        Meal.objects.create(survey_id=survey.id, **meal_data)
    # Add tags
    for tag in tags:
        t = Tag.objects.get(id=tag["id"])
        TaggedItem.objects.create(content_object=survey, tag=t)
    survey = SurveyAnswer.objects.get(id=survey.id)
    serializer = CommuteSerializer(survey)
    return Response(serializer.data, status=status.HTTP_201_CREATED)

Matt's avatar
Matt committed
@owns_ghgi(data_key="ghgi_id")
def save_travels(request, ghgi):
    data = request.data
    validate_synthesis(data["synthesis"])
Matt's avatar
Matt committed

    def make_travel(data_travel):
        data = copy.deepcopy(data_travel)
        data["ghgi_id"] = ghgi.id
        data.pop("sections")
        data.pop("names")
        tags = data.pop("tags")
        travel = Travel.objects.create(**data)
        for tag in tags:
            t = Tag.objects.get(id=tag["id"])
            TaggedItem.objects.create(content_object=travel, tag=t)
    def make_sections(travel, data):
        data_sections = data["sections"]
        sections = [
            TravelSection(
                travel=travel,
                distance=section["distance"],
                transportation=section["transportation"],
                carpooling=section["carpooling"],
                type=section["type"],
                isRoundTrip=section["isRoundTrip"],
                departure_city=section.get("departure_city"),
                departure_latitude=section.get("departure_latitude"),
                departure_longitude=section.get("departure_longitude"),
Matt's avatar
Matt committed
                departure_country=section.get("departure_country"),
                destination_city=section.get("destination_city"),
                destination_latitude=section.get("destination_latitude"),
                destination_longitude=section.get("destination_longitude"),
Matt's avatar
Matt committed
                destination_country=section.get("destination_country"),
            )
            for section in data_sections
        ]
    def make_names(travel, data):
        data_names = data["names"]
        names = [TravelNames(travel=travel, name=name) for name in data_names]
        return names
    # Delete all travels
Matt's avatar
Matt committed
    Travel.objects.filter(ghgi_id=ghgi.id).delete()

    # build / save all the travels
    all_travels = []
    for d in data["travels"]:
        all_travels.append(make_travel(d))

    # build all sections
    all_sections = []
    for (t, d) in zip(all_travels, request.data["travels"]):
        all_sections.extend(make_sections(t, d))
    TravelSection.objects.bulk_create(all_sections)

    # build names
    all_names = []
    for (t, d) in zip(all_travels, request.data["travels"]):
        all_names.extend(make_names(t, d))
    TravelNames.objects.bulk_create(all_names)

    # save travels intensity
    GHGI.objects.filter(id=ghgi.id).update(synthesis=request.data["synthesis"])
Matt's avatar
Matt committed
    travels = Travel.objects.filter(ghgi_id=ghgi.id)
    serializer = TravelSerializer(travels, many=True)
    return Response(serializer.data, status=status.HTTP_201_CREATED)
@api_view(["POST"])
Jerome Mariette's avatar
Jerome Mariette committed
@owns_ghgi(data_key="ghgi_id", allow_super_user=True)
def update_submitted(request, ghgi):
    validate_submitted(request.data["submitted"])
    GHGI.objects.filter(id=ghgi.id).update(submitted=request.data["submitted"])
    return Response(None, status=status.HTTP_204_NO_CONTENT)
Matt's avatar
Matt committed
@owns_ghgi(data_key="ghgi_id")
def update_survey_active(request, ghgi):
    validate_synthesis(request.data["synthesis"])
    GHGI.objects.filter(id=ghgi.id).update(
        commutesActive=request.data["commutesActive"],
        foodsActive=request.data["foodsActive"],
        synthesis=request.data["synthesis"],
    return Response(None, status=status.HTTP_204_NO_CONTENT)
Corentin's avatar
Corentin committed
@api_view(["GET"])
@owns_ghgi(data_key="ghgi_id", allow_super_user=True)
def get_ghgi_consumptions(request, ghgi):
    return Response(serialize_ghgi_with_consumptions(ghgi), status=status.HTTP_200_OK)
Jerome Mariette's avatar
Jerome Mariette committed

Corentin's avatar
Corentin committed
@api_view(["GET"])
Jerome Mariette's avatar
Jerome Mariette committed
@permission_classes([])
Jerome Mariette's avatar
Jerome Mariette committed
def get_ghgi_consumptions_by_uuid(request):
Corentin's avatar
Corentin committed
    uuid = request.query_params.get("uuid")
    try:
        ghgi = get_object_or_404(GHGI, uuid=uuid)
        return Response(
            serialize_ghgi_with_consumptions(ghgi), status=status.HTTP_200_OK
        )
Corentin's avatar
Corentin committed
    except:
        # Return a 404 anyway, so that the page not found is displayed to the
        # user
        return Response(None, status=status.HTTP_404_NOT_FOUND)
Jerome Mariette's avatar
Jerome Mariette committed

@api_view(["POST"])
def copy_data(request):
    if request.user.is_authenticated:
        if L1P5User.objects.get(email=request.user).is_superuser:
            from_ghgi = GHGI.objects.get(id=request.data["fromGHGI"])
            to_ghgi = GHGI.objects.get(id=request.data["toGHGI"])

            tagCategories = TagCategory.objects.filter(laboratory=to_ghgi.laboratory)
            tag = None
            for category in tagCategories:
                for t in category.tags.all():
                    if t.name == request.data["toTag"]:
                        tag = t

            classes = {
                "purchases": Purchase,
                "ractivities": ResearchActivity,
                "devices": ComputerDevice,
            }
            serializers = {
                "purchases": PurchaseSerializer,
                "ractivities": ResearchActivitySerializer,
                "devices": ComputerDeviceSerializer,
            }
            if request.data["module2copy"] in ["purchases", "ractivities", "devices"]:
Jerome Mariette's avatar
Jerome Mariette committed
                for item in classes[request.data["module2copy"]].objects.filter(
                    ghgi_id=from_ghgi.id
                ):
                    serializer = serializers[request.data["module2copy"]](
                        item, many=False
                    )
                    data = serializer.data
                    for key in ["id", "tags", "ghgi"]:
                        data.pop(key)
                    data["ghgi"] = to_ghgi
                    obj = classes[request.data["module2copy"]].objects.create(**data)
                    if tag is not None:
                        TaggedItem.objects.create(content_object=obj, tag=tag)

            elif request.data["module2copy"] in ["commutes", "foods"]:
                for survey in SurveyAnswer.objects.filter(ghgi_id=from_ghgi.id):
                    serializer = CommuteSerializer(survey, many=False)
                    data = serializer.data
                    sections_data = data.pop("sections")
                    meals_data = data.pop("meals")
                    for key in ["id", "tags", "ghgi", "seqID"]:
                        data.pop(key)
                    data["ghgi"] = to_ghgi
                    survey = SurveyAnswer.objects.create(**data)
Jerome Mariette's avatar
Jerome Mariette committed
                    SurveyAnswer.objects.filter(id=survey.id).update(seqID=survey.id)

                    if tag is not None:
                        TaggedItem.objects.create(content_object=survey, tag=tag)
                    for section in sections_data:
                        for key in ["id", "survey"]:
                            section.pop(key)
                        section["survey"] = survey
                        CommuteSection.objects.create(**section)
                    for meal in meals_data:
                        for key in ["id", "survey"]:
                            meal.pop(key)
                        meal["survey"] = survey
                        Meal.objects.create(**meal)

            elif request.data["module2copy"] == "travels":
                for item in Travel.objects.filter(ghgi_id=from_ghgi.id):
                    serializer = TravelSerializer(item, many=False)
                    data = serializer.data
                    section_data = data.pop("sections")
                    names_data = data.pop("names")
                    for key in ["id", "tags", "ghgi"]:
                        data.pop(key)
                    data["ghgi"] = to_ghgi
                    travel = Travel.objects.create(**data)
                    if tag is not None:
                        TaggedItem.objects.create(content_object=travel, tag=tag)
                    for name in names_data:
                        TravelNames.objects.create(name=name, travel=travel)
                    for section in section_data:
                        for key in ["id", "travel"]:
                            section.pop(key)
                        section["travel"] = travel
                        TravelSection.objects.create(**section)

            elif request.data["module2copy"] == "vehicles":
                for vehicle in Vehicle.objects.filter(laboratory=from_ghgi.laboratory):
Jerome Mariette's avatar
Jerome Mariette committed
                    serializer = VehicleWCSerializer(vehicle, many=False)
                    consumption = VehicleConsumption.objects.filter(
                        ghgi_id=from_ghgi.id, vehicle_id=vehicle.id
                    ).first()

                    if consumption:
                        data = serializer.data
                        for key in ["id", "laboratory"]:
                            data.pop(key)
                        data["laboratory"] = to_ghgi.laboratory
                        obj = Vehicle.objects.create(**data)
                        if tag is not None:
                            TaggedItem.objects.create(content_object=obj, tag=tag)
                        serializer = VehicleConsumptionSerializer(
                            consumption, many=False
                        )
                        data = serializer.data
                        for key in ["id", "ghgi", "vehicle"]:
                            data.pop(key)
                        data["ghgi"] = to_ghgi
                        data["vehicle"] = obj
                        VehicleConsumption.objects.create(**data)

            elif request.data["module2copy"] == "buildings":
Jerome Mariette's avatar
Jerome Mariette committed
                for building in Building.objects.filter(
                    laboratory=from_ghgi.laboratory
                ):
Jerome Mariette's avatar
Jerome Mariette committed
                    serializer = BuildingWCSerializer(building, many=False)
                    data = serializer.data
Jerome Mariette's avatar
Jerome Mariette committed
                    for key in ["id", "laboratory"]:
                        data.pop(key)
Jerome Mariette's avatar
Jerome Mariette committed
                    data["laboratory"] = to_ghgi.laboratory
                    obj = Building.objects.create(**data)
                    if tag is not None:
                        TaggedItem.objects.create(content_object=obj, tag=tag)

                    electricity = Electricity.objects.filter(
Jerome Mariette's avatar
Jerome Mariette committed
                        ghgi=from_ghgi, building_id=building.id
Jerome Mariette's avatar
Jerome Mariette committed
                    ).first()
                    if electricity:
                        serializer = ElectricitySerializer(electricity, many=False)
                        data = serializer.data
                        for key in ["id", "ghgi", "building"]:
                            data.pop(key)
                        data["ghgi"] = to_ghgi
                        data["building"] = obj
                        Electricity.objects.create(**data)

                    water = Water.objects.filter(
Jerome Mariette's avatar
Jerome Mariette committed
                        ghgi=from_ghgi, building_id=building.id
Jerome Mariette's avatar
Jerome Mariette committed
                    ).first()
                    if water:
                        serializer = WaterSerializer(water, many=False)
                        data = serializer.data
                        for key in ["id", "ghgi", "building"]:
                            data.pop(key)
                        data["ghgi"] = to_ghgi
                        data["building"] = obj
                        Water.objects.create(**data)

                    refrigerant = Refrigerant.objects.filter(
Jerome Mariette's avatar
Jerome Mariette committed
                        ghgi=from_ghgi, building_id=building.id
Jerome Mariette's avatar
Jerome Mariette committed
                    ).first()

                    if refrigerant:
                        serializer = RefrigerantSerializer(refrigerant, many=False)
                        data = serializer.data
                        for key in ["id", "ghgi", "building"]:
                            data.pop(key)
                        data["ghgi"] = to_ghgi
                        data["building"] = obj
                        Refrigerant.objects.create(**data)

                    selfconsumption = SelfConsumption.objects.filter(
Jerome Mariette's avatar
Jerome Mariette committed
                        ghgi=from_ghgi, building_id=building.id
Jerome Mariette's avatar
Jerome Mariette committed
                    ).first()
                    if selfconsumption:
Jerome Mariette's avatar
Jerome Mariette committed
                        serializer = SelfConsumptionSerializer(
                            selfconsumption, many=False
                        )
Jerome Mariette's avatar
Jerome Mariette committed
                        data = serializer.data
                        for key in ["id", "ghgi", "building"]:
                            data.pop(key)
                        data["ghgi"] = to_ghgi
                        data["building"] = obj
                        SelfConsumption.objects.create(**data)
Jerome Mariette's avatar
Jerome Mariette committed

Jerome Mariette's avatar
Jerome Mariette committed
                    heating = Heating.objects.filter(
Jerome Mariette's avatar
Jerome Mariette committed
                        ghgi=from_ghgi, building_id=building.id
Jerome Mariette's avatar
Jerome Mariette committed
                    ).first()
                    if heating:
                        serializer = HeatingSerializer(heating, many=False)
                        data = serializer.data
                        for key in ["id", "ghgi", "building"]:
                            data.pop(key)
                        data["ghgi"] = to_ghgi
                        data["building"] = obj
                        Heating.objects.create(**data)