diff --git a/alembic/versions/12049328fd0a_add_results_to_quiz_completions.py b/alembic/versions/12049328fd0a_add_results_to_quiz_completions.py new file mode 100644 index 00000000..f91f4ded --- /dev/null +++ b/alembic/versions/12049328fd0a_add_results_to_quiz_completions.py @@ -0,0 +1,32 @@ +"""add results to quiz completions + +Revision ID: 12049328fd0a +Revises: 291331bea272 +Create Date: 2024-09-11 10:23:37.753893 + +""" +from alembic import op +from sqlalchemy.dialects import postgresql +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '12049328fd0a' +down_revision = '291331bea272' +branch_labels = None +depends_on = None + + +def upgrade(): + # Add the 'responses' column + op.add_column('quiz_completions', sa.Column( + 'responses', + postgresql.JSONB(astext_type=sa.Text()), + nullable=False, + server_default=sa.text("'{}'::jsonb") + )) + + +def downgrade(): + # Remove the 'responses' column + op.drop_column('quiz_completions', 'responses') diff --git a/training-front-end/package-lock.json b/training-front-end/package-lock.json index 3790eed9..4f743591 100644 --- a/training-front-end/package-lock.json +++ b/training-front-end/package-lock.json @@ -6065,9 +6065,9 @@ "dev": true }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dev": true, "peer": true, "dependencies": { @@ -6079,7 +6079,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -8552,9 +8552,9 @@ "peer": true }, "node_modules/dset": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", - "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", "engines": { "node": ">=4" } @@ -8734,9 +8734,9 @@ } }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "peer": true, "engines": { @@ -9940,38 +9940,38 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", "dev": true, "peer": true, "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.10", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -10000,9 +10000,9 @@ "peer": true }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "dev": true, "peer": true }, @@ -10272,14 +10272,14 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dev": true, "peer": true, "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -15810,11 +15810,14 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", "dev": true, - "peer": true + "peer": true, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/merge-source-map": { "version": "1.1.0", @@ -20962,9 +20965,9 @@ } }, "node_modules/path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==" + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" }, "node_modules/path-type": { "version": "4.0.0", @@ -22178,13 +22181,13 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dev": true, "peer": true, "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -23660,9 +23663,9 @@ } }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dev": true, "peer": true, "dependencies": { @@ -23701,6 +23704,16 @@ "dev": true, "peer": true }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -23817,16 +23830,16 @@ } }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dev": true, "peer": true, "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" diff --git a/training-front-end/src/content/training_fleet_pc/lesson03.mdx b/training-front-end/src/content/training_fleet_pc/lesson03.mdx index 60efaa41..ea853c30 100644 --- a/training-front-end/src/content/training_fleet_pc/lesson03.mdx +++ b/training-front-end/src/content/training_fleet_pc/lesson03.mdx @@ -133,6 +133,6 @@ As part of the NDAA, Sections 1821 and 1826 contain prohibitions on using the GS **Section 1826** - PROHIBITION ON USE OF GOVERNMENT-ISSUED PURCHASE CARDS TO PURCHASE COVERED UNMANNED AIRCRAFT SYSTEMS FROM COVERED FOREIGN ENTITIES - Effective immediately, Government-issued Purchase Cards may not be used to procure any covered unmanned aircraft system from a covered foreign entity. -#### Cleared Drone Vendors +### Cleared Drone Vendors - A cleared list of drone vendors is available from the Defense Innovation Unit. - https://www.diu.mil/blue-uas-cleared-list diff --git a/training-front-end/src/content/training_purchase/lesson01.mdx b/training-front-end/src/content/training_purchase/lesson01.mdx index 80369d29..46e73c87 100644 --- a/training-front-end/src/content/training_purchase/lesson01.mdx +++ b/training-front-end/src/content/training_purchase/lesson01.mdx @@ -80,7 +80,7 @@ Card/account holders can purchase any commercially available supply or service w The GSA SmartPay Purchase card/account has a solid grounding in key statutes and regulations. Although many small-scale purchases are low in dollar amount, taken together, small-scale purchases account for billions of dollars in contracting and are a critical part of the government's acquisition process. Here are some of the key statutes and regulations: -- [Treasury Financial Manual, Chapter 4500 Government Purchase Cards](https://tfm.fiscal.treasury.gov/v1/p4/c450.html) prescribes procedures that apply to all departments and agencies that use the GSA SmartPay Purchase card/account. +- [Treasury Financial Manual, Chapter 4500 Government Purchase Cards](https://tfx.treasury.gov/tfm/volume1/part4/chapter-4500-government-purchase-cards) prescribes procedures that apply to all departments and agencies that use the GSA SmartPay Purchase card/account. - Purchases of supplies and services are covered by the [Federal Acquisition Regulation](https://www.acquisition.gov/) (FAR). - Management of property is covered by the [Federal Management Regulations](http://www.gsa.gov/federalmanagementregulation) (FMR). - [OMB Circular A-123, Appendix B [PDF, 71 pages]](https://www.whitehouse.gov/wp-content/uploads/2019/08/Issuance-of-Revised-Appendix-B-to-OMB-Circular-A-123.pdf) contains governmentwide guidelines on account management. diff --git a/training-front-end/src/content/training_purchase/lesson05.mdx b/training-front-end/src/content/training_purchase/lesson05.mdx index 88031fde..d1a11880 100644 --- a/training-front-end/src/content/training_purchase/lesson05.mdx +++ b/training-front-end/src/content/training_purchase/lesson05.mdx @@ -134,7 +134,7 @@ As part of the NDAA, Sections 1821 and 1826 contain prohibitions on using the GS **Section 1826** - PROHIBITION ON USE OF GOVERNMENT-ISSUED PURCHASE CARDS TO PURCHASE COVERED UNMANNED AIRCRAFT SYSTEMS FROM COVERED FOREIGN ENTITIES - Effective immediately, Government-issued Purchase Cards may not be used to procure any covered unmanned aircraft system from a covered foreign entity. -#### Cleared Drone Vendors +### Cleared Drone Vendors - A cleared list of drone vendors is available from the Defense Innovation Unit. - https://www.diu.mil/blue-uas-cleared-list @@ -179,7 +179,7 @@ Effective October 1, 2022, the following apply: - The maximum daily limit from a single payor is $24,999.99. - Total monthly transactions, based on a 30 day rolling period, from a single payor can be no more than $100,000.00. -The government’s card acceptance policies can be found in [Treasury Financial Manual (TFM) Vol. I, Part 5, Chapter 7000](https://tfm.fiscal.treasury.gov/v1/p5/c700). It also addresses limitations on credit card transactions. Additionally, consider the following: +The government’s card acceptance policies can be found in [Treasury Financial Manual (TFM) Vol. I, Part 5, Chapter 7000](https://tfx.treasury.gov/tfm/volume1/part5/chapter-7000-credit-and-debit-card-collection-transactions). It also addresses limitations on credit card transactions. Additionally, consider the following: - Customers cannot divide transactions into smaller pieces to evade these limits. - Treasury retains the option to change limits. One goal is to reduce the fees the government pays when it accepts the purchase card/account for large transactions. \ No newline at end of file diff --git a/training-front-end/src/content/training_purchase_pc/lesson03.mdx b/training-front-end/src/content/training_purchase_pc/lesson03.mdx index 04dd4ae1..b3990783 100644 --- a/training-front-end/src/content/training_purchase_pc/lesson03.mdx +++ b/training-front-end/src/content/training_purchase_pc/lesson03.mdx @@ -126,7 +126,7 @@ As part of the NDAA, Sections 1821 and 1826 contain prohibitions on using the GS **Section 1826** - PROHIBITION ON USE OF GOVERNMENT-ISSUED PURCHASE CARDS TO PURCHASE COVERED UNMANNED AIRCRAFT SYSTEMS FROM COVERED FOREIGN ENTITIES - Effective immediately, Government-issued Purchase Cards may not be used to procure any covered unmanned aircraft system from a covered foreign entity. -#### Cleared Drone Vendors +### Cleared Drone Vendors - A cleared list of drone vendors is available from the Defense Innovation Unit. - https://www.diu.mil/blue-uas-cleared-list @@ -171,7 +171,7 @@ Effective October 1, 2022, the following apply: - The maximum daily limit from a single payor is $24,999.99. - Total monthly transactions, based on a 30 day rolling period, from a single payor can be no more than $100,000.00. -The government’s card acceptance policies can be found in [Treasury Financial Manual (TFM) Vol. I, Part 5, Chapter 7000](https://tfm.fiscal.treasury.gov/v1/p5/c700). It also addresses limitations on credit card transactions. Additionally, consider the following: +The government’s card acceptance policies can be found in [Treasury Financial Manual (TFM) Vol. I, Part 5, Chapter 7000](https://tfx.treasury.gov/tfm/volume1/part5/chapter-7000-credit-and-debit-card-collection-transactions). It also addresses limitations on credit card transactions. Additionally, consider the following: - Customers cannot divide transactions into smaller pieces to evade these limits. - Treasury retains the option to change limits. One goal is to reduce the fees the government pays when it accepts the purchase card/account for large transactions. diff --git a/training-front-end/src/content/training_travel/lesson03.mdx b/training-front-end/src/content/training_travel/lesson03.mdx index eddc8bae..c8680579 100644 --- a/training-front-end/src/content/training_travel/lesson03.mdx +++ b/training-front-end/src/content/training_travel/lesson03.mdx @@ -95,6 +95,6 @@ As part of the NDAA, Sections 1821 and 1826 contain prohibitions on using the GS **Section 1826** - PROHIBITION ON USE OF GOVERNMENT-ISSUED PURCHASE CARDS TO PURCHASE COVERED UNMANNED AIRCRAFT SYSTEMS FROM COVERED FOREIGN ENTITIES - Effective immediately, Government-issued Purchase Cards may not be used to procure any covered unmanned aircraft system from a covered foreign entity. -#### Cleared Drone Vendors +### Cleared Drone Vendors - A cleared list of drone vendors is available from the Defense Innovation Unit. - https://www.diu.mil/blue-uas-cleared-list \ No newline at end of file diff --git a/training-front-end/src/content/training_travel_pc/lesson03.mdx b/training-front-end/src/content/training_travel_pc/lesson03.mdx index e9571e91..3cfd7b1e 100644 --- a/training-front-end/src/content/training_travel_pc/lesson03.mdx +++ b/training-front-end/src/content/training_travel_pc/lesson03.mdx @@ -156,6 +156,6 @@ As part of the NDAA, Sections 1821 and 1826 contain prohibitions on using the GS **Section 1826** - PROHIBITION ON USE OF GOVERNMENT-ISSUED PURCHASE CARDS TO PURCHASE COVERED UNMANNED AIRCRAFT SYSTEMS FROM COVERED FOREIGN ENTITIES - Effective immediately, Government-issued Purchase Cards may not be used to procure any covered unmanned aircraft system from a covered foreign entity. -#### Cleared Drone Vendors +### Cleared Drone Vendors - A cleared list of drone vendors is available from the Defense Innovation Unit. - https://www.diu.mil/blue-uas-cleared-list diff --git a/training/models/quiz_completion.py b/training/models/quiz_completion.py index dc92ed8a..28002643 100644 --- a/training/models/quiz_completion.py +++ b/training/models/quiz_completion.py @@ -2,6 +2,7 @@ from training.models import Base from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy import ForeignKey, func +from typing import Any class QuizCompletion(Base): @@ -12,3 +13,4 @@ class QuizCompletion(Base): user_id: Mapped[int] = mapped_column(ForeignKey("users.id")) passed: Mapped[bool] = mapped_column() submit_ts: Mapped[datetime] = mapped_column(server_default=func.now()) + responses: Mapped[dict[str, Any]] = mapped_column() diff --git a/training/repositories/quiz_completion.py b/training/repositories/quiz_completion.py index 6caee0c7..f3efb211 100644 --- a/training/repositories/quiz_completion.py +++ b/training/repositories/quiz_completion.py @@ -12,5 +12,6 @@ def create(self, quiz_completion: schemas.QuizCompletionCreate) -> models.QuizCo return self.save(models.QuizCompletion( quiz_id=quiz_completion.quiz_id, user_id=quiz_completion.user_id, - passed=quiz_completion.passed + passed=quiz_completion.passed, + responses=quiz_completion.responses )) diff --git a/training/schemas/quiz_completion.py b/training/schemas/quiz_completion.py index 3c90f0d4..c0576de2 100644 --- a/training/schemas/quiz_completion.py +++ b/training/schemas/quiz_completion.py @@ -1,11 +1,13 @@ from datetime import datetime from pydantic import ConfigDict, BaseModel +from typing import Any class QuizCompletionBase(BaseModel): quiz_id: int user_id: int passed: bool + responses: dict[str, Any] class QuizCompletionCreate(QuizCompletionBase): diff --git a/training/services/quiz.py b/training/services/quiz.py index bc7f03da..2f855029 100644 --- a/training/services/quiz.py +++ b/training/services/quiz.py @@ -97,10 +97,13 @@ def grade(self, quiz_id: int, user_id: int, submission: QuizSubmission) -> QuizG quiz_completion_id=None ) + responses_dict = submission.model_dump() + result = self.quiz_completion_repo.create(QuizCompletionCreate( quiz_id=quiz_id, user_id=user_id, passed=grade.passed, + responses=responses_dict )) grade.quiz_completion_id = result.id diff --git a/training/tests/test_quiz_completion_repository.py b/training/tests/test_quiz_completion_repository.py index 9e4ea425..cd77ecaa 100644 --- a/training/tests/test_quiz_completion_repository.py +++ b/training/tests/test_quiz_completion_repository.py @@ -12,7 +12,8 @@ def valid_quiz_completion_create( return schemas.QuizCompletionCreate( quiz_id=valid_quiz_ids[-1], user_id=valid_user_ids[-1], - passed=True + passed=True, + responses=dict([{'question_id': 0, 'response_ids': [1]}, {'question_id': 1, 'response_ids': [1]}, {'question_id': 2, 'response_ids': [2]}]) )