Skip to content

Commit

Permalink
Merge pull request #2866 from HHS/OPS-2836/Can-funding-received-api-e…
Browse files Browse the repository at this point in the history
…ndpoint

feat:Created-CAN-funding-received-endpoint
  • Loading branch information
Santi-3rd authored Oct 3, 2024
2 parents 29b873a + a2dca30 commit becd800
Show file tree
Hide file tree
Showing 9 changed files with 735 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""adding events for can funding received
Revision ID: acfeadc7868c
Revises: d5610e0988b0
Create Date: 2024-10-01 20:48:34.638703+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 = 'acfeadc7868c'
down_revision: Union[str, None] = 'd5610e0988b0'
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('ops', 'opseventtype', ['CREATE_BLI', 'UPDATE_BLI', 'DELETE_BLI', 'SEND_BLI_FOR_APPROVAL', 'CREATE_PROJECT', 'CREATE_NEW_AGREEMENT', 'UPDATE_AGREEMENT', 'DELETE_AGREEMENT', 'CREATE_NEW_CAN', 'UPDATE_CAN', 'DELETE_CAN', 'CREATE_CAN_FUNDING_RECEIVED', 'UPDATE_CAN_FUNDING_RECEIVED', 'DELETE_CAN_FUNDING_RECEIVED', 'CREATE_CAN_FUNDING_BUDGET', 'UPDATE_CAN_FUNDING_BUDGET', 'DELETE_CAN_FUNDING_BUDGET', 'ACKNOWLEDGE_NOTIFICATION', 'CREATE_BLI_PACKAGE', 'UPDATE_BLI_PACKAGE', 'CREATE_SERVICES_COMPONENT', 'UPDATE_SERVICES_COMPONENT', 'DELETE_SERVICES_COMPONENT', 'CREATE_PROCUREMENT_ACQUISITION_PLANNING', 'UPDATE_PROCUREMENT_ACQUISITION_PLANNING', 'DELETE_PROCUREMENT_ACQUISITION_PLANNING', 'CREATE_DOCUMENT', 'UPDATE_DOCUMENT', 'LOGIN_ATTEMPT', 'LOGOUT', 'GET_USER_DETAILS', 'CREATE_USER', 'UPDATE_USER', 'DEACTIVATE_USER'],
[TableReference(table_schema='ops', table_name='ops_event', column_name='event_type'), TableReference(table_schema='ops', table_name='ops_event_version', column_name='event_type')],
enum_values_to_rename=[])
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.sync_enum_values('ops', 'opseventtype', ['CREATE_BLI', 'UPDATE_BLI', 'DELETE_BLI', 'SEND_BLI_FOR_APPROVAL', 'CREATE_PROJECT', 'CREATE_NEW_AGREEMENT', 'UPDATE_AGREEMENT', 'DELETE_AGREEMENT', 'CREATE_NEW_CAN', 'UPDATE_CAN', 'DELETE_CAN', 'CREATE_CAN_FUNDING_BUDGET', 'UPDATE_CAN_FUNDING_BUDGET', 'DELETE_CAN_FUNDING_BUDGET', 'ACKNOWLEDGE_NOTIFICATION', 'CREATE_BLI_PACKAGE', 'UPDATE_BLI_PACKAGE', 'CREATE_SERVICES_COMPONENT', 'UPDATE_SERVICES_COMPONENT', 'DELETE_SERVICES_COMPONENT', 'CREATE_PROCUREMENT_ACQUISITION_PLANNING', 'UPDATE_PROCUREMENT_ACQUISITION_PLANNING', 'DELETE_PROCUREMENT_ACQUISITION_PLANNING', 'CREATE_DOCUMENT', 'UPDATE_DOCUMENT', 'LOGIN_ATTEMPT', 'LOGOUT', 'GET_USER_DETAILS', 'CREATE_USER', 'UPDATE_USER', 'DEACTIVATE_USER'],
[TableReference(table_schema='ops', table_name='ops_event', column_name='event_type'), TableReference(table_schema='ops', table_name='ops_event_version', column_name='event_type')],
enum_values_to_rename=[])
# ### end Alembic commands ###
5 changes: 5 additions & 0 deletions backend/models/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ class OpsEventType(Enum):
UPDATE_CAN = auto()
DELETE_CAN = auto()

# CAN Funding Received Related Events
CREATE_CAN_FUNDING_RECEIVED = auto()
UPDATE_CAN_FUNDING_RECEIVED = auto()
DELETE_CAN_FUNDING_RECEIVED = auto()

# CAN Funding Budget Related Events
CREATE_CAN_FUNDING_BUDGET = auto()
UPDATE_CAN_FUNDING_BUDGET = auto()
Expand Down
206 changes: 204 additions & 2 deletions backend/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,174 @@ paths:
description: Bad Request
"401":
description: Unauthorized
/api/v1/cans-funding-received/:
get:
tags:
- CANs Funding Received
operationId: getAllCANFundingReceived
summary: Get a list all CANs funding received
parameters:
- $ref: "#/components/parameters/simulatedError"
description: Get CANFundingReceived
responses:
"200":
description: OK
post:
tags:
- CANs Funding Received
operationId: createCANFundingReceived
summary: Create a new CANFundingReceived object
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateUpdateFundingReceived"
examples:
"0":
$ref: "#/components/examples/CreateUpdateFundingReceived"
responses:
"201":
description: Created
content:
application/json:
schema:
$ref: "#/components/schemas/FundingReceived"
"400":
description: Bad Request
"401":
description: Insufficient Privileges to use this endpoint.
/api/v1/can-funding-received/{can_funding_received_id}:
get:
tags:
- CAN Funding Received
summary: Get an individual CANFundingReceived
operationId: getCANFundingReceivedById
description: Get CANFundingReceived by Id
parameters:
- $ref: "#/components/parameters/simulatedError"
- in: path
name: can_funding_received_id
description: CAN Funding Received Id
required: true
schema:
type: integer
format: int32
minimum: 0
default: 1
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: "#/components/schemas/FundingReceived"
example:
"0":
$ref: "#/components/examples/FundingReceived"
"404":
description: The specified CANFundingReceived was not found.
patch:
tags:
- CANs Funding Received
summary: Update an existing CANFundingReceived with the provided fields
operationId: patchCANFundingReceived
parameters:
- $ref: "#/components/parameters/simulatedError"
- in: path
name: can_funding_received_id
description: CAN Funding Received Id
required: true
schema:
type: integer
format: int32
minimum: 0
default: 1
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateUpdateFundingReceived"
examples:
"0":
$ref: "#/components/examples/CreateUpdateFundingReceived"
responses:
"200":
description: CANFundingReceivedUpdated
content:
application/json:
schema:
$ref: "#/components/schemas/FundingReceived"
"400":
description: Bad Request
"401":
description: Insufficient Privileges to use this endpoint.
"404":
description: CANFundingReceived not found
put:
tags:
- CAN Funding Received
summary: Update an existing CANFundingReceived
operationId: putCanFundingReceived
parameters:
- $ref: "#/components/parameters/simulatedError"
- in: path
name: can_funding_received_id
description: CAN Funding Received Id
required: true
schema:
type: integer
format: int32
minimum: 0
default: 1
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/CreateUpdateFundingReceived"
examples:
"0":
$ref: "#/components/examples/CreateUpdateFundingReceived"
responses:
"200":
description: CAN Updated
content:
application/json:
schema:
$ref: "#/components/schemas/FundingReceived"
"400":
description: Bad Request
"401":
description: Insufficient Privileges to use this endpoint.
"404":
description: CAN not found
delete:
tags:
- CAN Funding Received
operationId: deleteCanFundingReceived
summary: Delete a CANFundingReceived
parameters:
- $ref: "#/components/parameters/simulatedError"
- in: path
name: can_funding_received_id
description: CANFundingReceived ID
required: true
schema:
type: integer
format: int32
minimum: 1
default: 1
responses:
"200":
description: OK
"400":
description: Bad Request
"401":
description: Unauthorized
"404":
description: Unable to find specified CANFundingReceived
/api/v1/can-funding-budgets/:
get:
tags:
Expand Down Expand Up @@ -2439,6 +2607,21 @@ components:
- id
- can_id
- fiscal_year
CreateUpdateFundingReceived:
description: A request object for the creation or updating of a FundingReceived
type: object
properties:
fiscal_year:
type: integer
can_id:
type: integer
funding:
type: number
notes:
type: string
required:
- fiscal_year
- can_id
FundingDetails:
description: Funding Detail Object
type: object
Expand Down Expand Up @@ -3940,14 +4123,33 @@ components:
portfolio_id: 6,
description: "A very good CAN to use for examples."
}
CreateUpdateCANFundingBudgetRequest:
CreateUpdateFundingReceived:
value: |
{
can_id: 500,
fiscal_year: 2024,
budget: 123456,
funding: 123456,
notes: "A new test Funding Budget"
}
FundingReceived:
value: |
{
funding: 1234567.89
can: {}
can_id: 500
display_name: CANFundingBudget.1
fiscal_year: 2024
id: 1
notes: "A funding budget"
versions: {}
CreateUpdateCANFundingBudgetRequest:
value: |
{
can_id: 500,
fiscal_year: 2024,
funding: 123456,
notes: "A new test Funding Funding"
}
FundingBudget:
value: |
{
Expand Down
95 changes: 95 additions & 0 deletions backend/ops_api/ops/resources/can_funding_received.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
from flask import Response, request
from flask_jwt_extended import jwt_required

from models import OpsEventType
from ops_api.ops.auth.auth_types import Permission, PermissionType
from ops_api.ops.auth.decorators import is_authorized
from ops_api.ops.base_views import BaseItemAPI, BaseListAPI
from ops_api.ops.schemas.cans import CreateUpdateFundingReceivedSchema, FundingReceivedSchema
from ops_api.ops.services.can_funding_received import CANFundingReceivedService
from ops_api.ops.utils.errors import error_simulator
from ops_api.ops.utils.events import OpsEventHandler
from ops_api.ops.utils.response import make_response_with_headers


class CANFundingReceivedItemAPI(BaseItemAPI):
def __init__(self, model):
super().__init__(model)
self.can_service = CANFundingReceivedService()

@is_authorized(PermissionType.GET, Permission.CAN)
def get(self, id: int) -> Response:
schema = FundingReceivedSchema()
item = self.can_service.get(id)
return make_response_with_headers(schema.dump(item))

@is_authorized(PermissionType.PATCH, Permission.CAN)
def patch(self, id: int) -> Response:
"""
Update a CANFundingReceived with only the fields provided in the request body.
"""
with OpsEventHandler(OpsEventType.UPDATE_CAN_FUNDING_RECEIVED) as meta:
request_data = request.get_json()
# Setting partial to true ignores any missing fields.
schema = CreateUpdateFundingReceivedSchema(partial=True)
serialized_request = schema.load(request_data)

updated_funding_received = self.can_service.update(serialized_request, id)
serialized_can_funding_received = schema.dump(updated_funding_received)
meta.metadata.update({"updated_funding_received": serialized_can_funding_received})
return make_response_with_headers(serialized_can_funding_received)

@is_authorized(PermissionType.PATCH, Permission.CAN)
def put(self, id: int) -> Response:
"""
Update a CANFundingReceived
"""
with OpsEventHandler(OpsEventType.UPDATE_CAN_FUNDING_RECEIVED) as meta:
request_data = request.get_json()
schema = CreateUpdateFundingReceivedSchema()
serialized_request = schema.load(request_data)

updated_funding_received = self.can_service.update(serialized_request, id)
serialized_funding_received = schema.dump(updated_funding_received)
meta.metadata.update({"updated_can_funding_budget": serialized_funding_received})
return make_response_with_headers(serialized_funding_received)

@is_authorized(PermissionType.DELETE, Permission.CAN)
def delete(self, id: int) -> Response:
"""
Delete a CANFundingReceived with given id.
"""
with OpsEventHandler(OpsEventType.DELETE_CAN_FUNDING_RECEIVED) as meta:
self.can_service.delete(id)
meta.metadata.update({"Deleted CANFundingReceived": id})
return make_response_with_headers({"message": "CANFundingReceived deleted", "id": id}, 200)


class CANFundingReceivedListAPI(BaseListAPI):
def __init__(self, model):
super().__init__(model)
self.can_service = CANFundingReceivedService()

@jwt_required()
@error_simulator
def get(self) -> Response:
result = self.can_service.get_list()
funding_received_schema = FundingReceivedSchema()
return make_response_with_headers([funding_received_schema.dump(can) for can in result])

@is_authorized(PermissionType.POST, Permission.CAN)
def post(self) -> Response:
"""
Create a new CANFundingReceived object
"""
with OpsEventHandler(OpsEventType.CREATE_CAN_FUNDING_RECEIVED) as meta:
request_data = request.get_json()
schema = CreateUpdateFundingReceivedSchema()
serialized_request = schema.load(request_data)

created_funding_received = self.can_service.create(serialized_request)

funding_received_schema = FundingReceivedSchema()
serialized_funding_received = funding_received_schema.dump(created_funding_received)
meta.metadata.update({"new_can_funding_received": serialized_funding_received})
return make_response_with_headers(serialized_funding_received, 201)
7 changes: 7 additions & 0 deletions backend/ops_api/ops/schemas/cans.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,13 @@ class FundingReceivedSchema(Schema):
updated_by_user = fields.Nested(SafeUserSchema(), allow_none=True)


class CreateUpdateFundingReceivedSchema(Schema):
fiscal_year = fields.Integer(required=True)
can_id = fields.Integer(required=True)
funding = fields.Integer(load_default=None)
notes = fields.String(load_default=None)


class CANSchema(BasicCANSchema):
budget_line_items = fields.List(fields.Nested(BudgetLineItemResponseSchema()), default=[])
funding_budgets = fields.List(fields.Nested(FundingBudgetSchema()), default=[])
Expand Down
Loading

0 comments on commit becd800

Please sign in to comment.