Skip to content

Commit 715f517

Browse files
committed
Merge branch 'develop' into TRACK-task#1331-B
2 parents 634376e + 2c168c8 commit 715f517

28 files changed

+1907
-1095
lines changed

epictrack-api/src/api/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ class TestConfig(_Config): # pylint: disable=too-few-public-methods
145145
JWT_OIDC_TEST_KEYS = {
146146
'keys': [
147147
{
148-
'kid': 'forms-flow-ai',
148+
'kid': 'epictrack',
149149
'kty': 'RSA',
150150
'alg': 'RS256',
151151
'use': 'sig',
Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,42 @@
1-
# Copyright © 2019 Province of British Columbia
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
14-
"""Model to handle all operations related to Issues."""
15-
16-
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
17-
from sqlalchemy.orm import relationship
18-
19-
from .base_model import BaseModelVersioned
20-
21-
22-
class WorkIssueUpdates(BaseModelVersioned):
23-
"""Model class for updates Connected to an issue."""
24-
25-
__tablename__ = 'work_issue_updates'
26-
27-
id = Column(Integer, primary_key=True, autoincrement=True)
28-
description = Column(String(2000), nullable=False)
29-
30-
is_approved = Column(Boolean(), default=False, nullable=True)
31-
approved_by = Column(String(255), default=None, nullable=True)
32-
33-
work_issue_id = Column(ForeignKey('work_issues.id'), nullable=False)
34-
work_issue = relationship('WorkIssues', back_populates='updates')
35-
36-
def as_dict(self): # pylint:disable=arguments-differ
37-
"""Return Json representation."""
38-
return {
39-
'id': self.id,
40-
'description': self.description,
41-
'work_issue_id': self.work_issue_id,
42-
}
1+
# Copyright © 2019 Province of British Columbia
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Model to handle all operations related to Issues."""
15+
16+
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
17+
from sqlalchemy.orm import relationship
18+
19+
from .base_model import BaseModelVersioned
20+
21+
22+
class WorkIssueUpdates(BaseModelVersioned):
23+
"""Model class for updates Connected to an issue."""
24+
25+
__tablename__ = 'work_issue_updates'
26+
27+
id = Column(Integer, primary_key=True, autoincrement=True)
28+
description = Column(String(2000), nullable=False)
29+
30+
is_approved = Column(Boolean(), default=False, nullable=True)
31+
approved_by = Column(String(255), default=None, nullable=True)
32+
33+
work_issue_id = Column(ForeignKey('work_issues.id'), nullable=False)
34+
work_issue = relationship('WorkIssues', back_populates='updates')
35+
36+
def as_dict(self): # pylint:disable=arguments-differ
37+
"""Return Json representation."""
38+
return {
39+
'id': self.id,
40+
'description': self.description,
41+
'work_issue_id': self.work_issue_id,
42+
}
Lines changed: 120 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,120 @@
1-
# Copyright © 2019 Province of British Columbia
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
14-
"""Resource for work issues endpoints."""
15-
from http import HTTPStatus
16-
17-
from flask import jsonify
18-
from flask_restx import Namespace, Resource, cors
19-
20-
from api.schemas import request as req
21-
from api.schemas import response as res
22-
from api.services import WorkIssuesService
23-
from api.utils.roles import Role
24-
from api.utils import auth, profiletime
25-
from api.utils.util import cors_preflight
26-
27-
API = Namespace("work-issues", description="Work Issues")
28-
29-
30-
@cors_preflight("GET, POST")
31-
@API.route("", methods=["GET", "POST", "OPTIONS"])
32-
class WorkStatus(Resource):
33-
"""Endpoint resource to manage work issues."""
34-
35-
@staticmethod
36-
@cors.crossdomain(origin="*")
37-
@auth.require
38-
def get(work_id):
39-
"""Return all active works."""
40-
works = WorkIssuesService.find_all_work_issues(work_id)
41-
return jsonify(res.WorkIssuesResponseSchema(many=True).dump(works)), HTTPStatus.OK
42-
43-
@staticmethod
44-
@cors.crossdomain(origin="*")
45-
@auth.require
46-
@profiletime
47-
def post(work_id):
48-
"""Create new work status"""
49-
request_dict = req.WorkIssuesParameterSchema().load(API.payload)
50-
work_issues = WorkIssuesService.create_work_issue_and_updates(work_id, request_dict)
51-
return res.WorkIssuesResponseSchema().dump(work_issues), HTTPStatus.CREATED
52-
53-
54-
@cors_preflight("PUT")
55-
@API.route("/<int:issue_id>", methods=["PUT", "OPTIONS"])
56-
class IssueUpdateEdits(Resource):
57-
"""Endpoint resource to manage updates/edits for a specific issue and its description."""
58-
59-
@staticmethod
60-
@cors.crossdomain(origin="*")
61-
@auth.require
62-
@profiletime
63-
def put(work_id, issue_id):
64-
"""Create a new update for the specified issue."""
65-
request_dict = req.WorkIssuesUpdateSchema().load(API.payload)
66-
work_issues = WorkIssuesService.edit_issue_update(work_id, issue_id, request_dict)
67-
return res.WorkIssuesResponseSchema().dump(work_issues), HTTPStatus.CREATED
68-
69-
70-
@cors_preflight("POST")
71-
@API.route("/<int:issue_id>/issue_update", methods=["POST", "OPTIONS"])
72-
class WorkIssueUpdate(Resource):
73-
"""Endpoint resource to manage updates for a specific issue."""
74-
75-
@staticmethod
76-
@cors.crossdomain(origin="*")
77-
@auth.require
78-
@profiletime
79-
def post(work_id, issue_id):
80-
"""Create a new update for the specified issue."""
81-
description_data = API.payload.get('description_data', None)
82-
if not description_data:
83-
return jsonify({'error': 'description_data is required'}), HTTPStatus.BAD_REQUEST
84-
work_issues = WorkIssuesService.add_work_issue_update(work_id, issue_id, description_data)
85-
return res.WorkIssuesResponseSchema().dump(work_issues), HTTPStatus.CREATED
86-
87-
88-
@cors_preflight("PATCH")
89-
@API.route("/<int:issue_id>/update/<int:update_id>/approve", methods=["PATCH", "OPTIONS"])
90-
class ApproveIssues(Resource):
91-
"""Endpoint resource to manage approving of work status."""
92-
93-
@staticmethod
94-
@cors.crossdomain(origin="*")
95-
@auth.has_one_of_roles([Role.CREATE.value])
96-
@profiletime
97-
# pylint: disable=unused-argument
98-
def patch(work_id, issue_id, update_id):
99-
"""Approve a work status."""
100-
approved_work_issues = WorkIssuesService.approve_work_issues(issue_id, update_id)
101-
102-
return res.WorkIssueUpdatesResponseSchema().dump(approved_work_issues), HTTPStatus.OK
1+
# Copyright © 2019 Province of British Columbia
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""Resource for work issues endpoints."""
15+
from http import HTTPStatus
16+
17+
from flask import jsonify
18+
from flask_restx import Namespace, Resource, cors
19+
20+
from api.schemas import request as req
21+
from api.schemas import response as res
22+
from api.services import WorkIssuesService
23+
from api.utils.roles import Role
24+
from api.utils import auth, profiletime
25+
from api.utils.util import cors_preflight
26+
27+
API = Namespace("work-issues", description="Work Issues")
28+
29+
30+
@cors_preflight("GET, POST")
31+
@API.route("", methods=["GET", "POST", "OPTIONS"])
32+
class WorkStatus(Resource):
33+
"""Endpoint resource to manage work issues."""
34+
35+
@staticmethod
36+
@cors.crossdomain(origin="*")
37+
@auth.require
38+
def get(work_id):
39+
"""Return all active works."""
40+
works = WorkIssuesService.find_all_work_issues(work_id)
41+
return jsonify(res.WorkIssuesResponseSchema(many=True).dump(works)), HTTPStatus.OK
42+
43+
@staticmethod
44+
@cors.crossdomain(origin="*")
45+
@auth.require
46+
@profiletime
47+
def post(work_id):
48+
"""Create new work status"""
49+
request_dict = req.WorkIssuesCreateParameterSchema().load(API.payload)
50+
work_issues = WorkIssuesService.create_work_issue_and_updates(work_id, request_dict)
51+
return res.WorkIssuesResponseSchema().dump(work_issues), HTTPStatus.CREATED
52+
53+
54+
@cors_preflight("PATCH")
55+
@API.route("/<int:issue_id>", methods=["PATCH", "OPTIONS"])
56+
class IssueUpdateEdits(Resource):
57+
"""Endpoint resource to manage updates/edits for a specific issue."""
58+
59+
@staticmethod
60+
@cors.crossdomain(origin="*")
61+
@auth.require
62+
@profiletime
63+
def patch(work_id, issue_id):
64+
"""Create a new update for the specified issue."""
65+
request_dict = req.WorkIssuesParameterSchema().load(API.payload)
66+
work_issues = WorkIssuesService.edit_issue(work_id, issue_id, request_dict)
67+
return res.WorkIssuesResponseSchema().dump(work_issues), HTTPStatus.CREATED
68+
69+
70+
@cors_preflight("POST")
71+
@API.route("/<int:issue_id>/issue_update", methods=["POST", "OPTIONS"])
72+
class WorkIssueUpdate(Resource):
73+
"""Endpoint resource to manage updates for a specific issue."""
74+
75+
@staticmethod
76+
@cors.crossdomain(origin="*")
77+
@auth.require
78+
@profiletime
79+
def post(work_id, issue_id):
80+
"""Create a new update for the specified issue."""
81+
description_data = API.payload.get('description_data', None)
82+
if not description_data:
83+
return jsonify({'error': 'description_data is required'}), HTTPStatus.BAD_REQUEST
84+
work_issues = WorkIssuesService.add_work_issue_update(work_id, issue_id, description_data)
85+
return res.WorkIssuesResponseSchema().dump(work_issues), HTTPStatus.CREATED
86+
87+
88+
@cors_preflight("PATCH")
89+
@API.route("/<int:issue_id>/update/<int:update_id>", methods=["PATCH", "OPTIONS"])
90+
class ApproveIssues(Resource):
91+
"""Endpoint resource to manage approving of work status."""
92+
93+
@staticmethod
94+
@cors.crossdomain(origin="*")
95+
@auth.has_one_of_roles([Role.CREATE.value])
96+
@profiletime
97+
# pylint: disable=unused-argument
98+
def patch(work_id, issue_id, update_id):
99+
"""Approve a work status."""
100+
request_dict = req.WorkIssuesUpdateSchema().load(API.payload)
101+
edited_issue_update = WorkIssuesService.edit_issue_update(work_id, issue_id, update_id, request_dict)
102+
103+
return res.WorkIssueUpdatesResponseSchema().dump(edited_issue_update), HTTPStatus.OK
104+
105+
106+
@cors_preflight("PATCH")
107+
@API.route("/<int:issue_id>/update/<int:update_id>/approve", methods=["PATCH", "OPTIONS"])
108+
class EditIssueUpdate(Resource):
109+
"""Endpoint resource to manage approving of work status."""
110+
111+
@staticmethod
112+
@cors.crossdomain(origin="*")
113+
@auth.has_one_of_roles([Role.CREATE.value])
114+
@profiletime
115+
# pylint: disable=unused-argument
116+
def patch(work_id, issue_id, update_id):
117+
"""Approve a work status."""
118+
approved_work_issues = WorkIssuesService.approve_work_issues(issue_id, update_id)
119+
120+
return res.WorkIssueUpdatesResponseSchema().dump(approved_work_issues), HTTPStatus.OK

epictrack-api/src/api/schemas/request/__init__.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,17 @@
5252
from .type_request import TypeIdPathParameterSchema
5353
from .user_group_request import UserGroupBodyParamSchema, UserGroupPathParamSchema
5454
from .work_request import (
55-
WorkBodyParameterSchema, WorkExistenceQueryParamSchema, WorkFirstNationImportBodyParamSchema,
56-
WorkFirstNationNotesBodySchema, WorkIdPathParameterSchema, WorkIdPhaseIdPathParameterSchema,
57-
WorkIssuesParameterSchema, WorkIssuesUpdateSchema, WorkNotesBodySchema, WorkPlanDownloadQueryParamSchema,
58-
WorkStatusParameterSchema, WorkTypeIdQueryParamSchema)
55+
WorkBodyParameterSchema,
56+
WorkExistenceQueryParamSchema,
57+
WorkFirstNationImportBodyParamSchema,
58+
WorkFirstNationNotesBodySchema,
59+
WorkIdPathParameterSchema,
60+
WorkIdPhaseIdPathParameterSchema,
61+
WorkIssuesCreateParameterSchema,
62+
WorkIssuesParameterSchema,
63+
WorkIssuesUpdateSchema,
64+
WorkNotesBodySchema,
65+
WorkPlanDownloadQueryParamSchema,
66+
WorkStatusParameterSchema,
67+
WorkTypeIdQueryParamSchema
68+
)

0 commit comments

Comments
 (0)