Encoding answers in the database

All data points entered in the system are stored as an instance of Answer (see database schema).

class survey.models.Unit(*args, **kwargs)

Unit in which an Answer.measured value is collected.

There are 6 types of units, each with its own use.

Unit Type

Description

SYSTEM_STANDARD

SI or International System of Units (ex: m, kg, J)

SYSTEM_IMPERIAL

Imperial/US customary measurement system (ex: ft, lb)

SYSTEM_RANK

Natural positive integer (ex: score, percentage)

SYSTEM_ENUMERATED

Finite set of named values (ex: Yes, No, N/A)

SYSTEM_FREETEXT

UTF-8 text string

SYSTEM_DATETIME

Date/time in Gregorian calendar

Entering quantitative measurements

Quantitative (numeric) measurements are recorded through the Records quantitative measurements API.

When baseline_at is specified, the measurement refers to a relative value since baseline_at. When baseline_at is not specified, the intent is to record an absolute measurement at time created_at.

Absolute measurements database encoding

Absolute measurements, for example the area occupied on the ground by a factory, are recorded as an Answer whose created_at field is the date of the measurement and a Sample whose created_at field is the date the record was created in the database.

POST /api/supplier-1/filters/accounts/factory-size/values HTTP/1.1
{
      "created_at":"2023-01-01",
      "items":[{
        "slug":"main-factory",
        "measured":"65",
        "unit":"m2"
      }]
}

TABLE survey_answer:

id

created_at

measured

unit

sample

question

1

2022-01-01

65

m2

1

factory-size

TABLE survey_sample:

id

created_at

account

campaign

is_frozen

1

2023-01-27

main-factory

null

true

Relative measurements database encoding

Relative measurements, like the amount of CO2 emissions for a factory during a time period are recorded as relative measurements between a start date (baseline_at) and an end date.

When no previous baseline exists (typically the first time a relative measurement is encoded), the API records a dummy record with value zero to encode the date at which the recording period started (i.e. baseline).

POST /api/supplier-1/filters/accounts/ghg-emissions/values HTTP/1.1
{
      "baseline_at":"2022-01-01",
      "created_at":"2023-01-01",
      "items":[{
        "slug":"main-factory",
        "measured":"12",
        "unit":"tons"
      }]
}

TABLE survey_answer:

id

created_at

measured

unit

sample

question

1

2022-01-01

0

tons

1

ghg-emissions

2

2023-01-01

12

tons

2

ghg-emissions

TABLE survey_sample:

id

created_at

account

campaign

is_frozen

1

2023-01-27

main-factory

null

true

2

2023-01-27

main-factory

null

true

When the specified baseline already has measurements recorded at that date, there is no gap in measurements, and thus the API doesn’t create an additional dummy record to encode the baseline date.

POST /api/supplier-1/filters/accounts/ghg-emissions/values HTTP/1.1
{
  "baseline_at":"2023-01-01",
  "created_at":"2024-01-01",
  "items":[{
    "slug":"main-factory",
    "measured":"8",
    "unit":"tons"
  }]
}

TABLE survey_answer:

id

created_at

measured

unit

sample

question

1

2022-01-01

0

tons

1

ghg-emissions

2

2023-01-01

12

tons

2

ghg-emissions

3

2024-01-01

8

tons

3

ghg-emissions

TABLE survey_sample:

id

created_at

account

campaign

is_frozen

1

2023-01-27

main-factory

null

true

2

2023-01-27

main-factory

null

true

3

2024-01-12

main-factory

null

true

Responding to a questionnaire

Answering a single choice question

In questionnaires (i.e. Campaign) with closed questions, phrased as for example: “Does your organization has a code of conduct?”, answers are saved in the database with a unit of type SYSTEM_ENUMERATED.

POST /api/supplier-1/sample/4c6675a5d5af46c796b8033a7731a86e/answers/code-of-conduct HTTP/1.1
{
      "measured": "Yes"
}

TABLE survey_answer:

id

created_at

measured

unit

sample

question

1

2023-01-01

1

yes-no

1

code-of-conduct

TABLE survey_choice:

id

unit

rank

text

1

yes-no

1

Yes

2

yes-no

2

No

TABLE survey_sample:

id

created_at

account

campaign

1

2023-01-27

supplier 1

sustainability

The primary key of the Choice model for the enumerated value matching the answer is saved in the Answer.measured field. Therefore most computations can be done on the Answer table alone, but you will need to do a SQL join with the survey_choice table for User Interface presentation.

Answering an open question

In questionnaires (i.e. Campaign) with open questions, phrased as for example: “What is your improvement plan?”, answers are saved in the database with a unit of type SYSTEM_FREETEXT.

POST /api/supplier-1/sample/4c6675a5d5af46c796b8033a7731a86e/answers/improvement-plan HTTP/1.1
{
      "measured": "Introducing recycle bins in cafetaria"
}

TABLE survey_answer:

id

created_at

measured

unit

sample

question

1

2023-01-01

1

freetext

1

improvement-plan

TABLE survey_choice:

id

unit

rank

text

1

freetext

Introducing recycle bins in cafetaria

TABLE survey_sample:

id

created_at

account

campaign

1

2023-01-27

supplier 1

sustainability

Answer.measured is used in that case to index the actual text inputed by a user inside the survey_choice table.

Reporting metrics over a time period

In the database, an answer about GHG Emissions of “10 Tons of CO2e in 2021” is encoded as follow in the database:

TABLE survey_answer:

id

created_at

measured

unit

sample

question

0

2023-01-27

10

tons-period

1

ghg-emissions

1

2023-01-27

2021-01-01

starts-at

1

ghg-emissions

2

2023-01-27

2021-12-31

ends-at

1

ghg-emissions

TABLE survey_sample:

id

created_at

account

campaign

1

2023-01-27

supplier 1

sustainability

Special cases

Absolute measurements in alternative units

Answer will be created such that

Answer.unit == Answer.question.default_unit