Views Package

Submodules

Accounts

seed.views.accounts.add_org(request, *args, **kwargs)

Creates a new organization.

Payload:

{
    'organization_name': The name of the new org,
    'user_id': the user id of the owner of the new org,
}

Returns:

{
    'status': 'success' or 'error',
    'message': 'message, if any',
    'organization_id': The ID of the new org, if created.
}
seed.views.accounts.add_user(request, *args, **kwargs)

Creates a new SEED user. One of ‘organization_id’ or ‘org_name’ is needed. Sends invitation email to the new user.

Payload:

{
    'organization_id': ID of an existing org to add the new user to,
    'org_name': Name of a new org to create with user as owner
    'first_name': First name of new user
    'last_name': Last name of new user
    'role': {
        'value': The permission level of new user within this org
            (one of member, viewer, owner)
    },
    'email': Email address of new user.
}

Returns:

{
    'status': 'success',
    'message': email address of new user,
    'org': name of the new org (or existing org),
    'org_created': True if new org created,
    'username': Username of new user
}
seed.views.accounts.add_user_to_organization(request, *args, **kwargs)

Adds an existing user to an organization.

Payload:

{
    'organization_id': The ID of the organization,
    'user_id': the user id of the owner of the new org,
}

Returns:

{
    'status': 'success' or 'error',
    'message': 'message, if any',
}
seed.views.accounts.create_sub_org(request, *args, **kwargs)

Creates a child org of a parent org.

Payload:

{
    'parent_org_id': ID of the parent org,
    'sub_org': {
        'name': Name of new sub org,
        'email': Email address of owner of sub org, which
                must already exist
    }
}

Returns:

{
    'status': 'success' or 'error',
    'message': Error message, if any,
    'organization_id': ID of newly-created org
}
seed.views.accounts.generate_api_key(request, *args, **kwargs)

generates a new API key

Returns:

{
    'status': 'success',
    'api_key': the new api key
}
seed.views.accounts.get_actions(request, *args, **kwargs)

returns all actions

seed.views.accounts.get_cleansing_rules(request, *args, **kwargs)

Returns the cleansing rules for an org.

Parameters:request
GET:Expects organization_id in the query string.

Returns:

{
 'status': 'success',
 'in_range_checking': An array of in-range error rules,
 'missing_matching_field': An array of fields to verify existence,
 'missing_values': An array of fields to ignore missing values
}
seed.views.accounts.get_organization(request, *args, **kwargs)

Retrieves a single organization by id.

GET:Expects ?organization_id=(:org_id)

Returns:

{'status': 'success or error', 'message': 'error message, if any',
 'organization':
    {'name': org name,
     'org_id': org's identifier (used with Authorization header),
     'id': org's identifier,
     'number_of_users': count of members of org,
     'user_is_owner': True if the user is owner of this org,
     'user_role': The role of user in this org (owner, viewer, member),
     'owners': [
         {
          'first_name': the owner's first name,
          'last_name': the owner's last name,
          'email': the owner's email address,
          'id': the owner's identifier (int)
          }
         ]
      'sub_orgs': [ a list of orgs having this org as parent, in
                    the same format...],
      'is_parent': True if this org contains suborgs,
      'num_buildings': Count of buildings belonging to this org
    }
}
seed.views.accounts.get_organizations(request, *args, **kwargs)

Retrieves all orgs the user has access to.

Returns:

{'organizations': [
    {'name': org name,
     'org_id': org's identifier (used with Authorization header),
     'id': org's identifier,
     'number_of_users': count of members of org,
     'user_is_owner': True if the user is owner of this org,
     'user_role': The role of user in this org (owner, viewer, member),
     'owners': [
                 {
                  'first_name': the owner's first name,
                  'last_name': the owner's last name,
                  'email': the owner's email address,
                  'id': the owner's identifier (int)
                 }
               ]
     'sub_orgs': [ a list of orgs having this org as parent, in
                the same format...],
     'is_parent': True if this org contains suborgs,
     'num_buildings': Count of buildings belonging to this org
    }...
   ]
}
seed.views.accounts.get_organizations_users(request, *args, **kwargs)

Retrieve all users belonging to an org.

Payload:

{'organization_id': org_id}

Returns:

{'status': 'success',
 'users': [
    {
     'first_name': the user's first name,
     'last_name': the user's last name,
     'email': the user's email address,
     'id': the user's identifier (int),
     'role': the user's role ('owner', 'member', 'viewer')
    }
  ]
}

Todo

check permissions that request.user is owner or admin and get more info about the users.

seed.views.accounts.get_query_threshold(request, *args, **kwargs)

Returns the “query_threshold” for an org. Searches from members of sibling orgs must return at least this many buildings from orgs they do not belong to, or else buildings from orgs they don’t belong to will be removed from the results.

GET:Expects organization_id in the query string.

Returns:

{
 'status': 'success',
 'query_threshold': The minimum number of buildings that must be
     returned from a search to avoid squelching non-member-org results.
}
seed.views.accounts.get_shared_buildings(request, *args, **kwargs)

gets the request user’s show_shared_buildings attr

seed.views.accounts.get_shared_fields(request, *args, **kwargs)

Retrieves all fields marked as shared for this org tree.

GET:Expects organization_id in the query string.

Returns:

{
 'status': 'success',
 'shared_fields': [
     {
      "title": Display name of field,
      "sort_column": database/search name of field,
      "class": css used for field,
      "title_class": css used for title,
      "type": data type of field,
          (One of: 'date', 'floor_area', 'link', 'string', 'number')
      "field_type": classification of field.  One of:
          'contact_information', 'building_information',
          'assessor', 'pm',
      "sortable": True if buildings can be sorted on this field,
     }
     ...
   ],
   'public_fields': [
       {
          "title": Display name of field,
          "sort_column": database/search name of field,
          "class": css used for field,
          "title_class": css used for title,
          "type": data type of field,
            (One of: 'date', 'floor_area', 'link', 'string', 'number')
          "field_type": classification of field.  One of:
              'contact_information', 'building_information',
              'assessor', 'pm',
          "sortable": True if buildings can be sorted on this field,
         }
         ...
   ]
}
seed.views.accounts.get_user_profile(request, *args, **kwargs)

Retrieves the request’s user’s first_name, last_name, email and api key if exists.

Returns:

{
    'status': 'success',
    'user': {
        'first_name': user's first name,
        'last_name': user's last name,
        'email': user's email,
        'api_key': user's API key
    }
}
seed.views.accounts.get_users(request, *args, **kwargs)

Retrieves all users’ email addresses and IDs. Only usable by superusers.

Returns:

{
    'users': [
        'email': 'Email address of user',
        'user_id': 'ID of user'
    ] ...
}
seed.views.accounts.is_authorized(request, *args, **kwargs)

checks the auth for a given action, if user is the owner of the parent org then True is returned for each action

Payload:

{
    'organization_id': 2,
    'actions': ['can_invite_member', 'can_remove_member']
}
Parameters:actions – from the json payload, a list of actions to check
Returns:a dict of with keys equal to the actions, and values as bool
seed.views.accounts.remove_user_from_org(request, *args, **kwargs)

Removes a user from an organization.

Payload:

{
    'organization_id': ID of the org,
    'user_id': ID of the user
}

Returns:

{
    'status': 'success' or 'error',
    'message': 'error message, if any'
}
seed.views.accounts.reset_cleansing_rules(request, *args, **kwargs)

Resets an organization’s data cleansing rules

Parameters:request
GET:Expects organization_id in the query string.

Returns:

{
 'status': 'success',
 'in_range_checking': An array of in-range error rules,
 'missing_matching_field': An array of fields to verify existence,
 'missing_values': An array of fields to ignore missing values
}
seed.views.accounts.save_cleansing_rules(request, *args, **kwargs)

Saves an organization’s settings: name, query threshold, shared fields

Payload:

{
    'organization_id: 2,
    'cleansing_rules': {
        'missing_matching_field': [
            {
                'field': 'address_line_1',
                'severity': 'error'
            }
        ],
        'missing_values': [
            {
                'field': 'address_line_1',
                'severity': 'error'
            }
        ],
        'in_range_checking': [
            {
                'field': 'conditioned_floor_area',
                'enabled': true,
                'type': 'number',
                'min': null,
                'max': 7000000,
                'severity': 'error',
                'units': 'square feet'
            },
        ]
    }
}

Returns:

{
    'status': 'success',
}
seed.views.accounts.save_org_settings(request, *args, **kwargs)

Saves an organization’s settings: name, query threshold, shared fields

Payload:

{
    'organization_id: 2,
    'organization': {
        'query_threshold': 2,
        'name': 'demo org',
        'fields': [  # All internal sibling org shared fields
            {
                'sort_column': database/search field name,
                    e.g. 'pm_property_id',
            }
        ],
        'public_fields': [  # All publicly shared fields
            {
                'sort_column': database/search field name,
                    e.g. 'pm_property_id',
            }
        ],
    }
}

Returns:

{
    'status': 'success or error',
    'message': 'error message, if any'
}
seed.views.accounts.search_public_fields(request, *args, **kwargs)

Search across all public fields.

Payload:

{
     'q': a string to search on (optional),
     'show_shared_buildings': True to include buildings from other
         orgs in this user's org tree,
     'order_by': which field to order by (e.g. pm_property_id),
     'import_file_id': ID of an import to limit search to,
     'filter_params': { a hash of Django-like filter parameters to limit
         query.  See seed.search.filter_other_params.  If 'project__slug'
         is included and set to a project's slug, buildings will include
         associated labels for that project.
       }
     'page': Which page of results to retrieve (default: 1),
     'number_per_page': Number of buildings to retrieve per page
                        (default: 10),
}

Returns:

{
     'status': 'success',
     'buildings': [
      { all fields for buildings the request user has access to;
        e.g.:
       'canonical_building': the CanonicalBuilding ID of the building,
       'pm_property_id': ID of building (from Portfolio Manager),
       'address_line_1': First line of building's address,
       'property_name': Building's name, if any
        ...
       }...
      ]
     'number_matching_search': Total number of buildings matching search,
     'number_returned': Number of buildings returned for this page
}
seed.views.accounts.set_default_organization(request, *args, **kwargs)

sets the user’s default organization

seed.views.accounts.set_password(request, *args, **kwargs)

sets/updates a user’s password, follows the min requirement of django password validation settings in config/settings/common.py

Payload:

{
    'current_password': current_password,
    'password_1': password_1,
    'password_2': password_2
}

Returns:

{
    'status': 'success'
}
seed.views.accounts.update_role(request, *args, **kwargs)

Sets a user’s role within an organization.

Payload:

{
    'organization_id': organization's id,
    'user_id': user's id,
    'role': one of 'owner', 'member', 'viewer'
}

Returns:

{
    'status': 'success or error',
    'message': 'error message, if any'
}
seed.views.accounts.update_user(request, *args, **kwargs)

Updates the request’s user’s first name, last name, and email

Payload:

{
 'user': {
          'first_name': :first_name,
          'last_name': :last_name,
          'email': :email
        }
}

Returns:

{
    'status': 'success',
    'user': {
        'first_name': user's first name,
        'last_name': user's last name,
        'email': user's email,
        'api_key': user's API key
    }
}

APIs

seed.views.api.get_api_schema(request, *args, **kwargs)

Returns a hash of all API endpoints and their descriptions.

Returns:

{
    '/example/url/here': {
        'name': endpoint name,
        'description': endpoint description
    }...
}

Todo

Should this require authentication? Should it limit the return to endpoints the user has authorization for?

Todo

Format docstrings better.

Main

seed.views.main.angular_js_tests(request)

Jasmine JS unit test code covering AngularJS unit tests and ran by ./manage.py harvest

seed.views.main.create_dataset(request, *args, **kwargs)

Creates a new empty dataset (ImportRecord).

Payload:

{
    "name": Name of new dataset, e.g. "2013 city compliance dataset"
    "organization_id": ID of the org this dataset belongs to
}

Returns:

{
    'status': 'success',
    'id': The ID of the newly-created ImportRecord,
    'name': The name of the newly-created ImportRecord
}
seed.views.main.create_pm_mapping(request, *args, **kwargs)

Create a mapping for PortfolioManager input columns.

Payload:

{
    columns: [ "name1", "name2", ... , "nameN"],
}

Returns:

{
    success: true,
    mapping: [
        [
            "name1",
            "mapped1", {
                bedes: true|false,
                numeric: true|false
            }
        ],
        [
            "name2",
            "mapped2", {
                bedes: true|false,
                numeric: true|false
            }
        ],
        ...
        [
            "nameN",
            "mappedN", {
                bedes: true|false,
                numeric: true|false
            }
        ]
    ]
}
-- OR --
{
    success: false,
    reason: "message goes here"
}
seed.views.main.delete_buildings(request, *args, **kwargs)

Deletes all BuildingSnapshots the user has selected.

Does not delete selected_buildings where the user is not a member or owner of the organization the selected building belongs. Since search shows buildings across all the orgs a user belongs, it’s possible for a building to belong to an org outside of org_id.

DELETE:Expects ‘org_id’ for the organization, and the search payload similar to add_buildings/create_project

Payload:

{
    'organization_id': 2,
    'search_payload': {
        'selected_buildings': [2, 3, 4],
        'select_all_checkbox': False,
        'filter_params': ... // see search_buildings
    }
}

Returns:

{
    'status': 'success' or 'error'
}
seed.views.main.delete_dataset(request, *args, **kwargs)

Deletes all files from a dataset and the dataset itself.

DELETE:Expects organization id and dataset id.

Payload:

{
    "dataset_id": 1,
    "organization_id": 1
}

Returns:

{
    'status': 'success' or 'error',
    'message': 'error message, if any'
}
seed.views.main.delete_duplicates_from_import_file(request, *args, **kwargs)

Retrieves the number of matched and unmatched BuildingSnapshots for a given ImportFile record.

GET:Expects import_file_id corresponding to the ImportFile in question.

Returns:

{
    "status": "success",
    "deleted": "Number of duplicates deleted"
}
seed.views.main.delete_file(request, *args, **kwargs)

Deletes an ImportFile from a dataset.

Payload:

{
    "file_id": "ImportFile id",
    "organization_id": "current user organization id as integer"
}

Returns:

{
    'status': 'success' or 'error',
    'message': 'error message, if any'
}
seed.views.main.delete_organization(request, *args, **kwargs)

Starts a background task to delete an organization and all related data.

GET:Expects ‘org_id’ for the organization.

Returns:

{
    'status': 'success' or 'error',
    'progress_key': ID of background job, for retrieving job progress
}
seed.views.main.delete_organization_buildings(request, *args, **kwargs)

Starts a background task to delete all BuildingSnapshots in an org.

GET:Expects ‘org_id’ for the organization.

Returns:

{
    'status': 'success' or 'error',
    'progress_key': ID of background job, for retrieving job progress
}
seed.views.main.export_buildings(request, *args, **kwargs)

Begins a building export process.

Payload:

{
    "export_name": "My Export",
    "export_type": "csv",
    "selected_buildings": [1234,], (optional list of building ids)
    "selected_fields": optional list of fields to export
    "select_all_checkbox": True // optional, defaults to False
}

Returns:

{
    "success": True,
    "status": "success",
    "export_id": export_id; see export_buildings_download,
    "total_buildings": count of buildings,
}
seed.views.main.export_buildings_download(request, *args, **kwargs)

Provides the url to a building export file.

Payload:

{
    "export_id": export_id from export_buildings
}

Returns:

{
    'success': True or False,
    'status': 'success or error',
    'message': 'error message, if any',
    'url': The url to the exported file.
}
seed.views.main.export_buildings_progress(request, *args, **kwargs)

Returns current progress on building export process.

Payload:

{
    "export_id": export_id from export_buildings
}

Returns:

{
    'success': True,
    'status': 'success or error',
    'message': 'error message, if any',
    'buildings_processed': number of buildings exported
}
seed.views.main.get_PM_filter_by_counts(request, *args, **kwargs)

Retrieves the number of matched and unmatched BuildingSnapshots for a given ImportFile record.

GET:Expects import_file_id corresponding to the ImportFile in question.

Returns:

{
    'status': 'success',
    'matched': Number of BuildingSnapshot objects that have matches,
    'unmatched': Number of BuildingSnapshot objects with no matches.
}
seed.views.main.get_aggregated_building_report_data(request, *args, **kwargs)

This method returns a set of aggregated building data for graphing. It expects as parameters

GET:
Parameters:
  • start_date – The starting date for the data series with the format YYYY-MM-DDThh:mm:ss+hhmm
  • end_date – The starting date for the data series with the format YYYY-MM-DDThh:mm:ss+hhmm
  • x_var – The variable name to be assigned to the “x” value in the returned data series
  • y_var – The variable name to be assigned to the “y” value in the returned data series
  • organization_id – The organization to be used when querying data.

The x_var values should be from the following set of variable names:

  • site_eui
  • source_eui
  • site_eui_weather_normalized
  • source_eui_weather_normalized
  • energy_score

The y_var values should be from the following set of variable names:

  • gross_floor_area
  • use_description
  • year_built

This method includes building record count information as part of the result JSON in a property called “building_counts.”

This property provides data on the total number of buildings available in each ‘year ending’ group, as well as the subset of those buildings that have actual data to graph. By sending these values in the result we allow the client to easily build a message like “200 of 250 buildings in this group have data.”

Returns:

{
    "status": "success",
    "chart_data": [
        {
            "yr_e": x - group by year ending
            "x": x, - median value in group
            "y": y - average value thing
        },
        {
            "yr_e": x
            "x": x,
            "y": y
        }
        ...
    ],
    "building_counts": [
        {
            "yr_e": string for year ending - group by
            "num_buildings": number of buildings in query results
            "num_buildings_w_data": number of buildings with valid data in this group, BOTH x and y?  # NOQA
        },
        ...
    ]
    "num_buildings": total number of buildings in query results,
    "num_buildings_w_data": total number of buildings with valid data in query results
}

parameters:
  • name: x_var description: Name of column in building snapshot database to be used for “x” axis required: true type: string paramType: query
  • name: y_var description: Name of column in building snapshot database to be used for “y” axis required: true type: string paramType: query
  • start_date: description: The start date for the entire dataset. required: true type: string paramType: query
  • end_date: description: The end date for the entire dataset. required: true type: string paramType: query
  • name: organization_id description: User’s organization which should be used to filter building query results required: true type: string paramType: query
type:
status:
required: true type: string
chart_data:
required: true type: array
building_counts:
required: true type: array
num_buildings:
required: true type: string
num_buildings_w_data:
required: true type: string
status code:
  • code: 400 message: Bad request, only GET method is available
  • code: 401 message: Not authenticated
  • code: 403 message: Insufficient rights to call this procedure
seed.views.main.get_building(request, *args, **kwargs)

Retrieves a building. If user doesn’t belong to the building’s org, fields will be masked to only those shared within the parent org’s structure.

GET:Expects building_id and organization_id in query string. building_id should be the canonical_building ID for the building, not the BuildingSnapshot id.

Returns:

{
     'status': 'success or error',
     'message': 'error message, if any',
     'building': {'id': the building's id,
                  'canonical_building': the canonical building ID,
                  other fields this user has access to...
     },
     'imported_buildings': [ A list of buildings imported to create
                             this building's record, in the same
                             format as 'building'
                           ],
     'projects': [
        // A list of the building's projects
        {
            "building": {
                "approved_date":07/30/2014,
                "compliant": null,
                "approver": "demo@seed.lbl.gov"
                "approved_date": "07/30/2014"
                "compliant": null
                "label": {
                    "color": "red",
                    "name": "non compliant",
                    id: 1
                }
            }
            "description": null
            "id": 3
            "is_compliance": false
            "last_modified_by_id": 1
            "name": "project 1"
            "owner_id": 1
            "slug": "project-1"
            "status": 1
            "super_organization_id": 1
        },
        . . .
    ],
     'user_role': role of user in this org,
     'user_org_id': the org id this user belongs to
}
seed.views.main.get_building_report_data(request, *args, **kwargs)

This method returns a set of x,y building data for graphing. It expects as parameters

GET:
Parameters:
  • start_date – The starting date for the data series with the format YYYY-MM-DD
  • end_date – The starting date for the data series with the format YYYY-MM-DD
  • x_var – The variable name to be assigned to the “x” value in the returned data series # NOQA
  • y_var – The variable name to be assigned to the “y” value in the returned data series # NOQA
  • organization_id – The organization to be used when querying data.

The x_var values should be from the following set of variable names:

  • site_eui
  • source_eui
  • site_eui_weather_normalized
  • source_eui_weather_normalized
  • energy_score

The y_var values should be from the following set of variable names:

  • gross_floor_area
  • use_description
  • year_built

This method includes building record count information as part of the result JSON in a property called “building_counts.”

This property provides data on the total number of buildings available in each ‘year ending’ group, as well as the subset of those buildings that have actual data to graph. By sending these values in the result we allow the client to easily build a message like “200 of 250 buildings in this group have data.”

Returns:

{
    "status": "success",
    "chart_data": [
        {
            "id" the id of the building,
            "yr_e": the year ending value for this data point
            "x": value for x var,
            "y": value for y var,
        },
        ...
    ],
    "building_counts": [
        {
            "yr_e": string for year ending
            "num_buildings": number of buildings in query results
            "num_buildings_w_data": number of buildings with valid data in query results
        },
        ...
    ]
    "num_buildings": total number of buildings in query results,
    "num_buildings_w_data": total number of buildings with valid data in the query results  # NOQA
}

parameters:
  • name: x_var description: Name of column in building snapshot database to be used for “x” axis required: true type: string paramType: query
  • name: y_var description: Name of column in building snapshot database to be used for “y” axis required: true type: string paramType: query
  • start_date: description: The start date for the entire dataset. required: true type: string paramType: query
  • end_date: description: The end date for the entire dataset. required: true type: string paramType: query
  • name: organization_id description: User’s organization which should be used to filter building query results required: true type: string paramType: query
  • name: aggregate description: Aggregates data based on internal rules (given x and y var) required: true type: string paramType: query
type:
status:
required: true type: string
chart_data:
required: true type: array
num_buildings:
required: true type: string
num_buildings_w_data:
required: true type: string
status codes:
  • code: 400 message: Bad request, only GET method is available
  • code: 401 message: Not authenticated
  • code: 403 message: Insufficient rights to call this procedure
seed.views.main.get_building_summary_report_data(request, *args, **kwargs)

This method returns basic, high-level data about a set of buildings, filtered by organization ID.

It expects as parameters

GET:
Parameters:
  • start_date – The starting date for the data series with the format YYYY-MM-DD
  • end_date – The starting date for the data series with the format YYYY-MM-DD

Returns:

{
    "status": "success",
    "summary_data":
    {
        "num_buildings": "number of buildings returned from query",
        "avg_eui": "average EUI for returned buildings",
        "avg_energy_score": "average energy score for returned buildings"
    }
}

Units for return values are as follows:

property units
avg_eui kBtu/ft2/yr

parameters:
  • name: organization_id description: User’s organization which should be used to filter building query results required: true type: string paramType: query
  • start_date: description: The start date for the entire dataset. required: true type: string paramType: query
  • end_date: description: The end date for the entire dataset. required: true type: string paramType: query
type:
status:
required: true type: string
summary_data:
required: true type: object
status codes:
  • code: 400 message: Bad request, only GET method is available
  • code: 401 message: Not authenticated
  • code: 403 message: Insufficient rights to call this procedure
seed.views.main.get_column_mapping_suggestions(request, *args, **kwargs)

Returns suggested mappings from an uploaded file’s headers to known data fields.

Payload:

{
    'import_file_id': The ID of the ImportRecord to examine,
    'org_id': The ID of the user's organization
}

Returns:

{
    'status': 'success',
    'suggested_column_mappings': {
        column header from file: [ (destination_column, score) ...]
        ...
    },
    'building_columns': [ a list of all possible columns ],
    'building_column_types': [a list of column types corresponding to building_columns],
}

..todo: The response of this method may not be correct. verify.

seed.views.main.get_columns(request, *args, **kwargs)

returns a JSON list of columns a user can select as his/her default

GET:Expects organization_id in the query string.
seed.views.main.get_coparents(request, *args, **kwargs)

Returns the nodes in the BuildingSnapshot tree that can be unmatched.

GET:Expects organization_id and building_id in the query string

Returns:

{
    'status': 'success',
    'coparents': [
        {
            "id": 333,
            "coparent": 223,
            "child": 443,
            "parents": [],
            "canonical_building_id": 1123
        },
        {
            "id": 223,
            "coparent": 333,
            "child": 443,
            "parents": [],
            "canonical_building_id": 1124
        },
        ...
    ]
}
seed.views.main.get_dataset(request, *args, **kwargs)

Retrieves ImportFile objects for one ImportRecord.

GET:Expects dataset_id for an ImportRecord in the query string.

Returns:

{
    'status': 'success',
    'dataset': {
        'name': Name of ImportRecord,
        'number_of_buildings': Total number of buildings in all ImportFiles for this dataset,
        'id': ID of ImportRecord,
        'updated_at': Timestamp of when ImportRecord was last modified,
        'last_modified_by': Email address of user making last change,
        'importfiles': [
            {
               'name': Name of associated ImportFile, e.g. 'buildings.csv',
               'number_of_buildings': Count of buildings in this file,
               'number_of_mappings': Number of mapped headers to fields,
               'number_of_cleanings': Number of fields cleaned,
               'source_type': Type of file (see source_types),
               'id': ID of ImportFile (needed for most operations)
            }
         ],
         ...
    },
        ...
}
seed.views.main.get_datasets(request, *args, **kwargs)

Retrieves all datasets for the user’s organization.

GET:Expects ‘organization_id’ of org to retrieve datasets from in query string.

Returns:

{
    'status': 'success',
    'datasets':  [
        {
            'name': Name of ImportRecord,
            'number_of_buildings': Total number of buildings in all ImportFiles,
            'id': ID of ImportRecord,
            'updated_at': Timestamp of when ImportRecord was last modified,
            'last_modified_by': Email address of user making last change,
            'importfiles': [
                {
                    'name': Name of associated ImportFile, e.g. 'buildings.csv',
                    'number_of_buildings': Count of buildings in this file,
                    'number_of_mappings': Number of mapped headers to fields,
                    'number_of_cleanings': Number of fields cleaned,
                    'source_type': Type of file (see source_types),
                    'id': ID of ImportFile (needed for most operations)
                }
            ],
            ...
        },
        ...
    ]
}
seed.views.main.get_datasets_count(request, *args, **kwargs)

Retrieves the number of datasets for an org.

GET:Expects organization_id in the query string.

Returns:

{
    'status': 'success',
    'datasets_count': Number of datasets belonging to this org.
}
seed.views.main.get_default_building_detail_columns(request, *args, **kwargs)

Get default columns for building detail view.

front end is expecting a JSON object with an array of field names

Returns:

{
    "columns": ["project_id", "name", "gross_floor_area"]
}
seed.views.main.get_default_columns(request, *args, **kwargs)

Get default columns for building list view.

front end is expecting a JSON object with an array of field names

Returns:

{
    "columns": ["project_id", "name", "gross_floor_area"]
}
seed.views.main.get_first_five_rows(request, *args, **kwargs)

Retrieves the first five rows of an ImportFile.

Payload:

{
    'import_file_id': The ID of the ImportFile
}

Returns:

{
    'status': 'success',
    'first_five_rows': [
        [list of strings of header row],
        [list of strings of first data row],
        ...
        [list of strings of fifth data row]
    ]
}
seed.views.main.get_import_file(request, *args, **kwargs)

Retrieves details about an ImportFile.

GET:Expects import_file_id in the query string.

Returns:

{
    'status': 'success',
    'import_file': {
        "name": Name of the uploaded file,
        "number_of_buildings": number of buildings in the file,
        "number_of_mappings": number of mapped columns,
        "number_of_cleanings": number of cleaned fields,
        "source_type": type of data in file, e.g. 'Assessed Raw'
        "number_of_matchings": Number of matched buildings in file,
        "id": ImportFile ID,
        'dataset': {
            'name': Name of ImportRecord file belongs to,
            'id': ID of ImportRecord file belongs to,
            'importfiles': [  # All ImportFiles in this ImportRecord, with
                # requested ImportFile first:
                {'name': Name of file,
                 'id': ID of ImportFile
                }
                ...
            ]
        }
    }
}
seed.views.main.get_match_tree(request, *args, **kwargs)

returns the BuildingSnapshot tree

GET:Expects organization_id and building_id in the query string

Returns:

{
    'status': 'success',
    'match_tree': [ // array of all the members of the tree
        {
            "id": 333,
            "coparent": 223,
            "child": 443,
            "parents": [],
            "canonical_building_id": 1123
        },
        {
            "id": 223,
            "coparent": 333,
            "child": 443,
            "parents": [],
            "canonical_building_id": 1124
        },
        {
            "id": 443,
            "coparent": null,
            "child": 9933,
            "parents": [333, 223],
            "canonical_building_id": 1123
        },
        {
            "id": 9933,
            "coparent": null,
            "child": null,
            "parents": [443],
            "canonical_building_id": 1123
        },
        ...
    ]
}
seed.views.main.get_raw_column_names(request, *args, **kwargs)

Retrieves a list of all column names from an ImportFile.

Payload:

{
    'import_file_id': The ID of the ImportFile
}

Returns:

{
    'status': 'success',
    'raw_columns': [
        list of strings of the header row of the ImportFile
    ]
}
seed.views.main.get_raw_report_data(from_date, end_date, orgs, x_var, y_var)

This method returns data used to generate graphing reports. It expects as parameters

GET:
Parameters:
  • from_date – The starting date for the data series. Date object.
  • end_date – The starting date for the data series with the format. Date object.
  • x_var – The variable name to be assigned to the “x” value in the returned data series.
  • y_var – The variable name to be assigned to the “y” value in the returned data series.
  • orgs – The organizations to be used when querying data.

The x and y variables should be column names in the BuildingSnapshot table. In theory they could be in the extra_data too and this works but is currently disabled.

Returns:

bldg_counts:  dict that looks like {year_ending : {"buildings_with_data": set(canonical ids), "buildings": set(canonical ids)}
                This is a collection of all year_ending dates and ids
                the canonical buildings that have data for that year
                and those that have files with that year_ending but no
                valid data point
                E.G.
                "bldg_counts"     (pending)
                    __len__    int: 8
                    2000-12-31 (140037191378512)    dict: {'buildings_w_data': set([35897, 35898]), 'buildings': set([35897, 35898])}
                    2001-12-31 (140037292480784)    dict: {'buildings_w_data': set([35897, 35898]), 'buildings': set([35897, 35898])}
data:   dict that looks like {canonical_id : { year_ending : {'x': x_value, 'y': y_value', 'release_date': release_date, 'building_snapshot_id': building_snapshot_id}}}
        This is the actual data for the building.  The top level key is
        the canonical_id then the next level is the year_ending and
        under that is the actual data.  NOTE:  If the year has files
        for a building but no valid data there will be an entry for
        that year but the x and y values will be None.

        E.G.
        "data"     (pending)
            __len__    int: 2
            35897 (28780560)    defaultdict: defaultdict(<type 'dict'>, {datetime.date(2001, 12, 31): {'y': 95.0, 'x': 88.0, 'release_date': datetime.datetime(2001, 12, 31, 0, 0), 'building_snapshot_id': 35854}, datetime.date(2004, 12, 31): {'y': 400000.0, 'x': 28.2, 'release_date': datetime.datetime(2004, 12, 31, 0, 0), 'building_snapshot_id': 35866}, datetime.date(2003, 12, 31): {'y': 400000.0, 'x': 28.2, 'release_date': datetime.datetime(2003, 12, 31, 0, 0), 'building_snapshot_id': 35860}, datetime.date(2009, 12, 31): {'y': 400000.0, 'x': 28.2, 'release_date': datetime.datetime(2009, 12, 31, 0, 0), 'building_snapshot_id': 35884}, datetime.date(2007, 12, 31): {'y': 400000.0, 'x': 28.2, 'release_date': datetime.datetime(2007, 12, 31, 0, 0), 'building_snapshot_id': 35878}, datetime.date(2000, 12, 31): {'y': 400000.0, 'x': 28.2, 'release_date': datetime.datetime(2000, 12, 31, 0, 0), 'building_snapshot_id': 35850}, datetime.date(2010, 12, 31): {'y': 111.0, 'x': 21.0, 'release_date': datetime.datetime(2011, 12, 31, 0, 0...  # NOQA
                __len__    int: 8
                2000-12-31 (140037191378512)    dict: {'y': 400000.0, 'x': 28.2, 'release_date': datetime.datetime(2000, 12, 31, 0, 0), 'building_snapshot_id': 35850}  # NOQA
                2001-12-31 (140037292480784)    dict: {'y': 95.0, 'x': 88.0, 'release_date': datetime.datetime(2001, 12, 31, 0, 0), 'building_snapshot_id': 35854}  # NOQA
seed.views.main.get_total_number_of_buildings_for_user(request, *args, **kwargs)

gets a count of all buildings in the user’s organizations

seed.views.main.home(request, *args, **kwargs)

the main view for the app Sets in the context for the django template:

  • app_urls: a json object of all the URLs that is loaded in the JS global namespace
  • username: the request user’s username (first and last name)
  • AWS_UPLOAD_BUCKET_NAME: S3 direct upload bucket
  • AWS_CLIENT_ACCESS_KEY: S3 direct upload client key
  • FILE_UPLOAD_DESTINATION: ‘S3’ or ‘filesystem’
seed.views.main.progress(request, *args, **kwargs)

Get the progress (percent complete) for a task.

Payload:

{
    'progress_key': The progress key from starting a background task
}

Returns:

{
    'progress_key': The same progress key,
    'progress': Percent completion
}
seed.views.main.public_search(request, *args, **kwargs)

the public API unauthenticated endpoint

see search_buildings for the non-public version

seed.views.main.remap_buildings(request, *args, **kwargs)

Re-run the background task to remap buildings as if it hadn’t happened at all. Deletes mapped buildings for a given ImportRecord, resets status.

NB: will not work if buildings have been merged into CanonicalBuilings.

Payload:

{
    'file_id': The ID of the ImportFile to be remapped
}

Returns:

{
    'status': 'success' or 'error',
    'progress_key': ID of background job, for retrieving job progress
}
seed.views.main.save_column_mappings(request, *args, **kwargs)

Saves the mappings between the raw headers of an ImportFile and the destination fields in the BuildingSnapshot model.

Valid source_type values are found in seed.models.SEED_DATA_SOURCES

Payload:

{
    "import_file_id": ID of the ImportFile record,
    "mappings": [
        ["destination_field": "raw_field"],  #direct mapping
        ["destination_field2":
            ["raw_field1", "raw_field2"],  #concatenated mapping
        ...
    ]
}

Returns:

{'status': 'success'}
seed.views.main.save_match(request, *args, **kwargs)

Adds or removes a match between two BuildingSnapshots. Creating a match creates a new BuildingSnapshot with merged data.

Payload:

{
    'organization_id': current user organization id,
    'source_building_id': ID of first BuildingSnapshot,
    'target_building_id': ID of second BuildingSnapshot,
    'create_match': True to create match, False to remove it,
    'organization_id': ID of user's organization
}

Returns:

{
    'status': 'success',
    'child_id': The ID of the newly-created BuildingSnapshot
                containing merged data from the two parents.
}
seed.views.main.save_raw_data(request, *args, **kwargs)

Starts a background task to import raw data from an ImportFile into BuildingSnapshot objects.

Payload:

{
    'file_id': The ID of the ImportFile to be saved
}

Returns:

{
    'status': 'success' or 'error',
    'progress_key': ID of background job, for retrieving job progress
}
seed.views.main.search_building_snapshots(request, *args, **kwargs)

Retrieves a paginated list of BuildingSnapshots matching search params.

Payload:

{
    'q': a string to search on (optional),
    'order_by': which field to order by (e.g. pm_property_id),
    'import_file_id': ID of an import to limit search to,
    'filter_params': {
        a hash of Django-like filter parameters to limit query.  See seed.search.filter_other_params.
    }
    'page': Which page of results to retrieve (default: 1),
    'number_per_page': Number of buildings to retrieve per page (default: 10),
}

Returns:

{
    'status': 'success',
    'buildings': [
        {
            'pm_property_id': ID of building (from Portfolio Manager),
            'address_line_1': First line of building's address,
            'property_name': Building's name, if any
        }...
    ]
    'number_matching_search': Total number of buildings matching search,
    'number_returned': Number of buildings returned for this page
}
seed.views.main.search_buildings(request, *args, **kwargs)

Retrieves a paginated list of CanonicalBuildings matching search params.

Payload:

{
    'q': a string to search on (optional),
    'show_shared_buildings': True to include buildings from other orgs in this user's org tree,
    'order_by': which field to order by (e.g. pm_property_id),
    'import_file_id': ID of an import to limit search to,
    'filter_params': {
        a hash of Django-like filter parameters to limit query.  See seed.search.filter_other_params.
        If 'project__slug' is included and set to a project's slug, buildings will include associated labels
        for that project.
    }
    'page': Which page of results to retrieve (default: 1),
    'number_per_page': Number of buildings to retrieve per page (default: 10),
}

Returns:

{
    'status': 'success',
    'buildings': [
        {
            all fields for buildings the request user has access to, e.g.:
                'canonical_building': the CanonicalBuilding ID of the building,
                'pm_property_id': ID of building (from Portfolio Manager),
                'address_line_1': First line of building's address,
                'property_name': Building's name, if any
            ...
        }...
    ]
    'number_matching_search': Total number of buildings matching search,
    'number_returned': Number of buildings returned for this page
}
seed.views.main.set_default_building_detail_columns(request, *args, **kwargs)
seed.views.main.set_default_columns(request, *args, **kwargs)
seed.views.main.start_mapping(request, *args, **kwargs)

Starts a background task to convert imported raw data into BuildingSnapshots, using user’s column mappings.

Payload:

{
    'file_id': The ID of the ImportFile to be mapped
}

Returns:

{
    'status': 'success' or 'error',
    'progress_key': ID of background job, for retrieving job progress
}
seed.views.main.start_system_matching(request, *args, **kwargs)

Starts a background task to attempt automatic matching between buildings in an ImportFile with other existing buildings within the same org.

Payload:

{
    'file_id': The ID of the ImportFile to be matched
}

Returns:

{
    'status': 'success' or 'error',
    'progress_key': ID of background job, for retrieving job progress
}
seed.views.main.update_building(request, *args, **kwargs)

Manually updates a building’s record. Creates a new BuildingSnapshot for the resulting changes.

PUT:

Payload:

{
    "organization_id": "organization id as integer",
    "building":
        {
            "canonical_building": "canonical building ID as integer"
            "fieldname": "value",
            "...": "Remaining fields in the BuildingSnapshot; see get_columns() endpoint for complete list."
        }
}

Returns:

{
    "status": "success",
    "child_id": "The ID of the newly-created BuildingSnapshot"
}
seed.views.main.update_dataset(request, *args, **kwargs)

Updates the name of a dataset.

Payload:

{
    'dataset': {
        'id': The ID of the Import Record,
        'name': The new name for the ImportRecord
    }
}

Returns:

{
    'status': 'success' or 'error',
    'message': 'error message, if any'
}
seed.views.main.version(request, *args, **kwargs)

Returns the SEED version and current git sha

Meters

seed.views.meters.add_meter_to_building(request, *args, **kwargs)

Will add a building to an existing meter.

Payload:

{
    'organization_id': 435,
    'building_id': 342,
    'meter_name': 'Unit 34.',
    'energy_type': 'Electricity',
    'energy_units': 'kWh'
}
seed.views.meters.add_timeseries(request, *args, **kwargs)

Add time series data for a meter.

Payload:

{
    'organization_id': 435,
    'meter_id': 34,
    'timeseries': [
        {
            'begin_time': 2342342232,
            'end_time': 23423433433,
            'cost': 232.23,
        }...
    ]
}
seed.views.meters.get_meters(request, *args, **kwargs)

Returns all of the meters for a building.

Expected GET params:

building_id: int, unique identifier for a (canonical) building.

seed.views.meters.get_timeseries(request, *args, **kwargs)

Return all time series data for a building, grouped by meter.

Expected GET params:

meter_id: int, unique identifier for the meter. offset: int, the offset from the most recent meter data to begin showing. num: int, the number of results to show.

Projects

seed.views.projects.add_buildings_to_project(request, *args, **kwargs)

Adds buildings to a project.

Payload:

{
 'project':
     {
      'project_slug': Identifier of project to add buildings to,
      'selected_buildings': A list of building IDs to add to project
     }
}

Returns:

{
 'status': 'success' or 'error',
 'message': 'error message, if any',
 'project_loading_cache_key': Identifier for the background job, to
     determine the job's progress
}
seed.views.projects.create_project(request, *args, **kwargs)

Creates a new project. @TODO: What’s a compliance_type?

Payload:

{
 'organization_id': ID of org to associate new project with,
 'project': {
   'name': name of new project,
   'compliance_type': description of type of compliance,
   'description': description of new project,
   'end_date': Timestamp for when project ends,
   'deadline_date': Timestamp for compliance deadline
 }
}

Returns:

{
 'status': 'success' or 'error',
 'message': 'error message, if any',
 'project_slug': Identifier of new project, if project successfully
                 created
}
seed.views.projects.delete_project(request, *args, **kwargs)

Deletes a project.

Payload:

{
 'project_slug': identifier (slug) for the project
 'organization_id': ID of the org the project belongs to
}

Returns:

{
 'status': 'success or error',
 'message': 'error message, if any'
}
seed.views.projects.get_adding_buildings_to_project_status_percentage(request, *args, **kwargs)

Returns percentage complete of background task for adding building to project.

Payload:

{
    'project_loading_cache_key': Job identifier from add_buildings_to_project.
}

Returns:

{
    'status': 'success',
        'progress_object': {
            'status': job status,
            'progress': percent job done (out of 100),
            'progress_key': progress_key for job,
            'numerator': number buildings added,
            'denominator': total number of building to add
    }
}
seed.views.projects.get_project(request, *args, **kwargs)

Retrieves details about a project.

GET:Expects the project’s identifier (slug) as project_slug in the query string. Expects an organization_id (to which project belongs) in the query string.

Returns:

{
 'name': project's name,
 'slug': project's identifier,
 'status': 'active',
 'number_of_buildings': Count of buildings associated with project
 'last_modified': Timestamp when project last changed
 'last_modified_by': {
    'first_name': first name of user that made last change,
    'last_name': last name,
    'email': email address,
    },
 'is_compliance': True if project is a compliance project,
 'compliance_type': Description of compliance type,
 'deadline_date': Timestamp of when compliance is due,
 'end_date': Timestamp of end of project
}
seed.views.projects.get_projects(request, *args, **kwargs)

Retrieves all projects for a given organization.

GET:Expects organization_id in query string.

Returns:

{
    'status': 'success',
    'projects': [
        {
            'name': project's name,
            'slug': project's identifier,
            'status': 'active',
            'number_of_buildings': Count of buildings associated with project
            'last_modified': Timestamp when project last changed
            'last_modified_by': {
                'first_name': first name of user that made last change,
                'last_name': last name,
                'email': email address,
            },
            'is_compliance': True if project is a compliance project,
            'compliance_type': Description of compliance type,
            'deadline_date': Timestamp of when compliance is due,
            'end_date': Timestamp of end of project
        }...
    ]
}
seed.views.projects.get_projects_count(request, *args, **kwargs)

Returns the number of projects within the org tree to which a user belongs. Counts projects in parent orgs and sibling orgs.

GET:Expects organization_id for the user’s org.

Returns:

{
    'status': 'success',
    'projects_count': count of projects
}
seed.views.projects.move_buildings(request, *args, **kwargs)

Moves buildings from one project to another.

Payload:

{
    "buildings": [
        "00010811",
        "00010809"
    ],
    "copy": true to copy the buildings, false to move,
    "search_params": {
        "filter_params": {
            "project__slug": "proj-1"
        },
        "project_slug": 34,
        "q": "hotels"
    },
    "select_all_checkbox": false,
    "source_project_slug": "proj-1",
    "target_project_slug": "proj-2"
}

Returns:

{ 'status': 'success' }
seed.views.projects.remove_buildings_from_project(request, *args, **kwargs)

Removes buildings from a project.

Payload:

{
 'project':
     {
      'slug': Identifier of project to remove buildings from,
      'selected_buildings': A list of building IDs to remove
     }
}

Returns:

{
 'status': 'success' or 'error',
 'message': 'error message, if any',
 'project_removing_cache_key': Identifier for the background job, to
     determine the job's progress
}
seed.views.projects.update_project(request, *args, **kwargs)

Updates an existing project’s details and compliance info.

Payload:

{
 'project': {
   'project_slug': Identifier of project to update,
   'name': new name for project,
   'is_compliance': true or false,
   'compliance_type': (optional if 'is_compliance' is false)
        description of type of compliance,
   'end_date': (optional if 'is_compliance' is false) Timestamp for
        when project ends,
   'deadline_date': (optional if 'is_compliance' is false) Timestamp
        for compliance deadline
 }
}

Returns:

{
 'status': 'success' or 'error',
 'message': 'error message, if any'
}
seed.views.projects.update_project_building(request, *args, **kwargs)

Updates extra information about the building/project relationship. In particular, whether the building is compliant and who approved it.

Payload:

{
    'project_slug': identifier of project,
    'building_id': ID of building,
    'label': {
        'id': Identifier of label to apply.
    }
}

Returns:

{
    'status': 'success',
    'approved_date': Timestamp of change (now),
    'approver': Email address of user making change.
}

Module contents