diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 894099f9f7..37ace2e5c1 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -10,4 +10,4 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - uses: wagoid/commitlint-github-action@0184f5a228ee06430bb9e67d65f73a1a6767496a # v6 + - uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6 diff --git a/.github/workflows/security_semgrep.yml b/.github/workflows/security_semgrep.yml index 3dea719188..42911202f4 100644 --- a/.github/workflows/security_semgrep.yml +++ b/.github/workflows/security_semgrep.yml @@ -9,7 +9,7 @@ jobs: name: Semgrep Analyze runs-on: ubuntu-latest container: - image: returntocorp/semgrep@sha256:5145f6e54f8df98588023f56c66acbf25d0909c2655c16e4c104eefca6e735f8 # 1.47.0 + image: returntocorp/semgrep@sha256:bab808dd7cfef7584b75c36ce4f9bd29cb421cd0a383eee925350e4645360bae # 1.47.0 steps: - name: Checkout uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 diff --git a/backend/alembic/versions/2025_01_14_0616-52bf070f396e_adding_new_can_method_of_transfer.py b/backend/alembic/versions/2025_01_14_0616-52bf070f396e_adding_new_can_method_of_transfer.py new file mode 100644 index 0000000000..9d2d2d633e --- /dev/null +++ b/backend/alembic/versions/2025_01_14_0616-52bf070f396e_adding_new_can_method_of_transfer.py @@ -0,0 +1,42 @@ +"""adding new CAN Method of Transfer + +Revision ID: 52bf070f396e +Revises: 6615ac7d4eea +Create Date: 2025-01-14 06:16:14.707739+00:00 + +""" +from typing import Sequence, Union + +import sqlalchemy as sa +from alembic import op +from alembic_postgresql_enum import TableReference + +# revision identifiers, used by Alembic. +revision: str = '52bf070f396e' +down_revision: Union[str, None] = '6615ac7d4eea' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.sync_enum_values( + enum_schema='ops', + enum_name='canmethodoftransfer', + new_values=['DIRECT', 'COST_SHARE', 'IAA', 'IDDA', 'OTHER'], + affected_columns=[TableReference(table_schema='ops', table_name='can_funding_details', column_name='method_of_transfer'), TableReference(table_schema='ops', table_name='can_funding_details_version', column_name='method_of_transfer')], + enum_values_to_rename=[], + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.sync_enum_values( + enum_schema='ops', + enum_name='canmethodoftransfer', + new_values=['DIRECT', 'COST_SHARE', 'IAA', 'IDDA'], + affected_columns=[TableReference(table_schema='ops', table_name='can_funding_details', column_name='method_of_transfer'), TableReference(table_schema='ops', table_name='can_funding_details_version', column_name='method_of_transfer')], + enum_values_to_rename=[], + ) + # ### end Alembic commands ### diff --git a/backend/data_tools/Pipfile b/backend/data_tools/Pipfile index 899eeba185..b36656b269 100644 --- a/backend/data_tools/Pipfile +++ b/backend/data_tools/Pipfile @@ -12,7 +12,7 @@ cfenv = "==0.5.3" typing-extensions = "==4.12.2" desert = "2022.9.22" sqlalchemy-continuum = "==1.4.2" -marshmallow-sqlalchemy = "==1.2.0" +marshmallow-sqlalchemy = "==1.3.0" marshmallow-enum = "==1.5.1" alembic = "==1.14.0" alembic-postgresql-enum = "==1.5.0" diff --git a/backend/data_tools/Pipfile.lock b/backend/data_tools/Pipfile.lock index b82cf78ebb..99e68639bb 100644 --- a/backend/data_tools/Pipfile.lock +++ b/backend/data_tools/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "74fcd73860c1ee22542ecff4bc8fa0379cd0334e4ce1b2e891697a75a83452ba" + "sha256": "b98f3fe9f8401d96c8dbf0fa874117c61301de2b7f65000abec7e94db7ba0d47" }, "pipfile-spec": 6, "requires": { @@ -725,12 +725,12 @@ }, "marshmallow-sqlalchemy": { "hashes": [ - "sha256:9787e95d52dc39f351db1ca47a7ca30b593e4f02b5c54592680bc03ce8ce0e79", - "sha256:e1d97ab55103683a9f737a99f6d7eea286135c1eb23ba7d865fa3bc05358f530" + "sha256:5ddf583dd75fdf5ab31df76987cda2ba91942996ba5d577e92d6748fa93a5f52", + "sha256:7a0e90e817bcbcebe01961645811596714cdeb786d101a2903dc5841723e7c8f" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==1.2.0" + "version": "==1.3.0" }, "msal": { "hashes": [ diff --git a/backend/models/cans.py b/backend/models/cans.py index d67f6190cd..031e23c8d8 100644 --- a/backend/models/cans.py +++ b/backend/models/cans.py @@ -18,6 +18,7 @@ class CANMethodOfTransfer(Enum): COST_SHARE = auto() IAA = auto() IDDA = auto() + OTHER = auto() class CANStatus(Enum): diff --git a/backend/openapi.yml b/backend/openapi.yml index 7222c8ee41..ea24d57f2f 100644 --- a/backend/openapi.yml +++ b/backend/openapi.yml @@ -1161,6 +1161,7 @@ paths: - COST_SHARE - IAA - IDDA + - OTHER example: [ "DIRECT", "IAA" ] - name: portfolio in: query @@ -2967,6 +2968,7 @@ components: - COST_SHARE - IAA - IDDA + - OTHER sub_allowance: type: string FundingDetails: @@ -3002,6 +3004,7 @@ components: - COST_SHARE - IAA - IDDA + - OTHER sub_allowance: type: string created_on: diff --git a/backend/ops_api/Pipfile b/backend/ops_api/Pipfile index 2837bdf32f..100ab92339 100644 --- a/backend/ops_api/Pipfile +++ b/backend/ops_api/Pipfile @@ -18,7 +18,7 @@ loguru = "==0.7.3" markupsafe = "==3.0.2" marshmallow-dataclass = "==8.7.1" marshmallow-enum = "==1.5.1" -marshmallow-sqlalchemy = "==1.2.0" +marshmallow-sqlalchemy = "==1.3.0" mypy = "==1.14.1" psycopg2-binary = "==2.9.10" PyYAML = "==6.0.2" diff --git a/backend/ops_api/Pipfile.lock b/backend/ops_api/Pipfile.lock index 8892ec4c82..30bde1c9f4 100644 --- a/backend/ops_api/Pipfile.lock +++ b/backend/ops_api/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "6bfcb597221410c3b5f72852679e6024a63f50ec980a24f1a17a856eaa67dc50" + "sha256": "b514bfba0499ff2a801fb28edc119c77968cfe60269c9dbff7a9e061a3b32464" }, "pipfile-spec": 6, "requires": { @@ -574,12 +574,12 @@ }, "marshmallow-sqlalchemy": { "hashes": [ - "sha256:9787e95d52dc39f351db1ca47a7ca30b593e4f02b5c54592680bc03ce8ce0e79", - "sha256:e1d97ab55103683a9f737a99f6d7eea286135c1eb23ba7d865fa3bc05358f530" + "sha256:5ddf583dd75fdf5ab31df76987cda2ba91942996ba5d577e92d6748fa93a5f52", + "sha256:7a0e90e817bcbcebe01961645811596714cdeb786d101a2903dc5841723e7c8f" ], "index": "pypi", "markers": "python_version >= '3.9'", - "version": "==1.2.0" + "version": "==1.3.0" }, "msal": { "hashes": [ diff --git a/backend/ops_api/tests/ops/funding_summary/test_can_funding_summary.py b/backend/ops_api/tests/ops/funding_summary/test_can_funding_summary.py index 5a385b5489..a38012bc72 100644 --- a/backend/ops_api/tests/ops/funding_summary/test_can_funding_summary.py +++ b/backend/ops_api/tests/ops/funding_summary/test_can_funding_summary.py @@ -64,7 +64,7 @@ def test_can_get_can_funding_summary_invalid_transfer(auth_client: FlaskClient): query_params = f"can_ids={0}&fiscal_year=2023&transfer=INVALID" response = auth_client.get(f"/api/v1/can-funding-summary?{query_params}") assert response.status_code == 400 - assert response.json["Error"] == "Invalid 'transfer' value. Must be one of: DIRECT, COST_SHARE, IAA, IDDA." + assert response.json["Error"] == "Invalid 'transfer' value. Must be one of: DIRECT, COST_SHARE, IAA, IDDA, OTHER." def test_can_get_can_funding_summary_mou_transfer(auth_client: FlaskClient): diff --git a/frontend/bun.lockb b/frontend/bun.lockb index dfad1e3471..618f859a13 100755 Binary files a/frontend/bun.lockb and b/frontend/bun.lockb differ diff --git a/frontend/package.json b/frontend/package.json index 0a3df27a3b..059b408b74 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -7,7 +7,7 @@ "dependencies": { "@azure/storage-blob": "12.26.0", "@eslint/compat": "1.2.4", - "@eslint/js": "9.17.0", + "@eslint/js": "9.18.0", "@fortawesome/fontawesome-svg-core": "6.5.2", "@fortawesome/free-regular-svg-icons": "6.5.2", "@fortawesome/free-solid-svg-icons": "6.5.2", @@ -21,7 +21,7 @@ "axios": "1.7.9", "clsx": "2.1.1", "crypto-random-string": "5.0.0", - "eslint": "9.17.0", + "eslint": "9.18.0", "eslint-config-prettier": "9.1.0", "eslint-plugin-cypress": "4.1.0", "eslint-plugin-import": "2.31.0", diff --git a/frontend/src/components/CANs/CAN.constants.js b/frontend/src/components/CANs/CAN.constants.js index 87c246bee8..fb1b9835ff 100644 --- a/frontend/src/components/CANs/CAN.constants.js +++ b/frontend/src/components/CANs/CAN.constants.js @@ -2,5 +2,6 @@ export const CAN_TRANSFER = { DIRECT: "Direct", COST_SHARE: "COST_SHARE", IDDA: "IDDA", - IAA: "IAA" + IAA: "IAA", + OTHER: "OTHER" }; diff --git a/frontend/src/components/CANs/CANTransferComboBox/CANTransferComboBox.jsx b/frontend/src/components/CANs/CANTransferComboBox/CANTransferComboBox.jsx index 7c85435a73..be73514744 100644 --- a/frontend/src/components/CANs/CANTransferComboBox/CANTransferComboBox.jsx +++ b/frontend/src/components/CANs/CANTransferComboBox/CANTransferComboBox.jsx @@ -28,7 +28,8 @@ const CANTransferComboBox = ({ { id: 1, title: convertCodeForDisplay("methodOfTransfer", CAN_TRANSFER.DIRECT) }, { id: 2, title: convertCodeForDisplay("methodOfTransfer", CAN_TRANSFER.COST_SHARE) }, { id: 3, title: convertCodeForDisplay("methodOfTransfer", CAN_TRANSFER.IAA) }, - { id: 4, title: convertCodeForDisplay("methodOfTransfer", CAN_TRANSFER.IDDA) } + { id: 4, title: convertCodeForDisplay("methodOfTransfer", CAN_TRANSFER.IDDA) }, + { id: 5, title: convertCodeForDisplay("methodOfTransfer", CAN_TRANSFER.OTHER) } ]; return ( diff --git a/frontend/src/helpers/utils.js b/frontend/src/helpers/utils.js index 57e6980cf9..1353beda37 100644 --- a/frontend/src/helpers/utils.js +++ b/frontend/src/helpers/utils.js @@ -185,9 +185,10 @@ export const codesToDisplayText = { }, methodOfTransfer: { DIRECT: "Direct", - COST_SHARE: "MOU", + COST_SHARE: "Cost Share", IAA: "IAA", - IDDA: "IDDA" + IDDA: "IDDA", + OTHER: "Other" }, project: { ADMINISTRATIVE_AND_SUPPORT: "Admin & Support", diff --git a/frontend/src/pages/cans/list/CanList.jsx b/frontend/src/pages/cans/list/CanList.jsx index 424fdc5616..19f9f35aed 100644 --- a/frontend/src/pages/cans/list/CanList.jsx +++ b/frontend/src/pages/cans/list/CanList.jsx @@ -36,8 +36,7 @@ const CanList = () => { const activePeriodIds = filters.activePeriod.map((ap) => ap.id); const transferTitles = filters.transfer.map((t) => { - const title = t.title.toUpperCase(); - return title === "MOU" ? "COST_SHARE" : title; + return t.title.toUpperCase(); }); const portfolioAbbreviations = filters.portfolio.map((p) => p.abbr);