Skip to content

Commit 79b27bd

Browse files
authored
Merge pull request #192 from dinesh-aot/COMP-304
Inspection Requirement DELETE
2 parents 75eb99a + b0cfd28 commit 79b27bd

19 files changed

+497
-59
lines changed

.github/workflows/api-ci.yml

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ jobs:
6363
JWT_OIDC_TEST_ISSUER: "http://localhost:8081/auth/"
6464
JWT_OIDC_TEST_ALGORITHMS: "RS256"
6565
JWT_OIDC_TEST_WELL_KNOWN_CONFIG: "http://localhost:8081/auth/realms/eao-epic/.well-known/openid-configuration"
66+
DB_ECRPT_KEY: f1e3a5a4b9e86357d5b3041ac719d411
6667

6768
runs-on: ubuntu-20.04
6869

@@ -105,20 +106,20 @@ jobs:
105106
run: |
106107
make test
107108
108-
- name: Sets Codecov branch name
109-
run: |
110-
echo "CODECOV_BRANCH=PR_${{github.head_ref}}" >> $GITHUB_ENV
111-
if: github.event_name == 'pull_request'
109+
# - name: Sets Codecov branch name
110+
# run: |
111+
# echo "CODECOV_BRANCH=PR_${{github.head_ref}}" >> $GITHUB_ENV
112+
# if: github.event_name == 'pull_request'
112113

113-
- name: Upload coverage to Codecov
114-
uses: codecov/codecov-action@v4
115-
with:
116-
flags: compliance-api
117-
name: codecov-compliance-api
118-
fail_ci_if_error: true
119-
verbose: true
120-
token: ${{ secrets.CODECOV_TOKEN }}
121-
override_branch: ${{ env.CODECOV_BRANCH }}
114+
# - name: Upload coverage to Codecov
115+
# uses: codecov/codecov-action@v4
116+
# with:
117+
# flags: compliance-api
118+
# name: codecov-compliance-api
119+
# fail_ci_if_error: true
120+
# verbose: true
121+
# token: ${{ secrets.CODECOV_TOKEN }}
122+
# override_branch: ${{ env.CODECOV_BRANCH }}
122123

123124
build:
124125
runs-on: ubuntu-20.04
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
"""enforcement requirement map
2+
3+
Revision ID: 20afe60273fb
4+
Revises: 6c3b6755e2dc
5+
Create Date: 2025-01-10 11:12:08.390578
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
11+
12+
# revision identifiers, used by Alembic.
13+
revision = '20afe60273fb'
14+
down_revision = '6c3b6755e2dc'
15+
branch_labels = None
16+
depends_on = None
17+
18+
19+
def upgrade():
20+
# ### commands auto generated by Alembic - please adjust! ###
21+
op.create_table('inspection_req_enforcement_mappings_version',
22+
sa.Column('id', sa.Integer(), autoincrement=False, nullable=False, comment='The unique identifier'),
23+
sa.Column('requirement_id', sa.Integer(), autoincrement=False, nullable=True, comment='The requirement id'),
24+
sa.Column('enforcement_action_id', sa.Integer(), autoincrement=False, nullable=True, comment='The enforcement action taken on the requirement'),
25+
sa.Column('created_date', sa.DateTime(), autoincrement=False, nullable=True),
26+
sa.Column('updated_date', sa.DateTime(), autoincrement=False, nullable=True),
27+
sa.Column('created_by', sa.String(length=100), autoincrement=False, nullable=True),
28+
sa.Column('updated_by', sa.String(length=100), autoincrement=False, nullable=True),
29+
sa.Column('is_active', sa.Boolean(), server_default='t', autoincrement=False, nullable=True),
30+
sa.Column('is_deleted', sa.Boolean(), server_default='f', autoincrement=False, nullable=True),
31+
sa.Column('transaction_id', sa.BigInteger(), autoincrement=False, nullable=False),
32+
sa.Column('end_transaction_id', sa.BigInteger(), nullable=True),
33+
sa.Column('operation_type', sa.SmallInteger(), nullable=False),
34+
sa.Column('requirement_id_mod', sa.Boolean(), server_default=sa.text('false'), nullable=False),
35+
sa.Column('enforcement_action_id_mod', sa.Boolean(), server_default=sa.text('false'), nullable=False),
36+
sa.Column('created_date_mod', sa.Boolean(), server_default=sa.text('false'), nullable=False),
37+
sa.Column('updated_date_mod', sa.Boolean(), server_default=sa.text('false'), nullable=False),
38+
sa.Column('created_by_mod', sa.Boolean(), server_default=sa.text('false'), nullable=False),
39+
sa.Column('updated_by_mod', sa.Boolean(), server_default=sa.text('false'), nullable=False),
40+
sa.Column('is_active_mod', sa.Boolean(), server_default=sa.text('false'), nullable=False),
41+
sa.Column('is_deleted_mod', sa.Boolean(), server_default=sa.text('false'), nullable=False),
42+
sa.PrimaryKeyConstraint('id', 'transaction_id')
43+
)
44+
with op.batch_alter_table('inspection_req_enforcement_mappings_version', schema=None) as batch_op:
45+
batch_op.create_index(batch_op.f('ix_inspection_req_enforcement_mappings_version_end_transaction_id'), ['end_transaction_id'], unique=False)
46+
batch_op.create_index(batch_op.f('ix_inspection_req_enforcement_mappings_version_operation_type'), ['operation_type'], unique=False)
47+
batch_op.create_index(batch_op.f('ix_inspection_req_enforcement_mappings_version_transaction_id'), ['transaction_id'], unique=False)
48+
49+
op.create_table('inspection_req_enforcement_mappings',
50+
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False, comment='The unique identifier'),
51+
sa.Column('requirement_id', sa.Integer(), nullable=False, comment='The requirement id'),
52+
sa.Column('enforcement_action_id', sa.Integer(), nullable=True, comment='The enforcement action taken on the requirement'),
53+
sa.Column('created_date', sa.DateTime(), nullable=False),
54+
sa.Column('updated_date', sa.DateTime(), nullable=True),
55+
sa.Column('created_by', sa.String(length=100), nullable=False),
56+
sa.Column('updated_by', sa.String(length=100), nullable=True),
57+
sa.Column('is_active', sa.Boolean(), server_default='t', nullable=False),
58+
sa.Column('is_deleted', sa.Boolean(), server_default='f', nullable=False),
59+
sa.ForeignKeyConstraint(['enforcement_action_id'], ['enforcement_action_options.id'], name='insepction_req_enf_map_fkey'),
60+
sa.ForeignKeyConstraint(['requirement_id'], ['inspection_requirements.id'], name='inspection_req_enf_map_req_id_fkey'),
61+
sa.PrimaryKeyConstraint('id')
62+
)
63+
with op.batch_alter_table('inspection_requirements', schema=None) as batch_op:
64+
batch_op.create_index('unique_non_deleted_sort_order', ['inspection_id', 'sort_order'], unique=True, postgresql_where=sa.text('is_deleted IS false'))
65+
batch_op.drop_constraint('insepction_requirements_enforcement_action_fkey', type_='foreignkey')
66+
batch_op.drop_column('enforcement_action_id')
67+
68+
with op.batch_alter_table('inspection_requirements_version', schema=None) as batch_op:
69+
batch_op.drop_column('enforcement_action_id')
70+
batch_op.drop_column('enforcement_action_id_mod')
71+
72+
# ### end Alembic commands ###
73+
74+
75+
def downgrade():
76+
# ### commands auto generated by Alembic - please adjust! ###
77+
with op.batch_alter_table('inspection_requirements_version', schema=None) as batch_op:
78+
batch_op.add_column(sa.Column('enforcement_action_id_mod', sa.BOOLEAN(), server_default=sa.text('false'), autoincrement=False, nullable=False))
79+
batch_op.add_column(sa.Column('enforcement_action_id', sa.INTEGER(), autoincrement=False, nullable=True, comment='The enforcement action taken on the requirement'))
80+
81+
with op.batch_alter_table('inspection_requirements', schema=None) as batch_op:
82+
batch_op.add_column(sa.Column('enforcement_action_id', sa.INTEGER(), autoincrement=False, nullable=True, comment='The enforcement action taken on the requirement'))
83+
batch_op.create_foreign_key('insepction_requirements_enforcement_action_fkey', 'enforcement_action_options', ['enforcement_action_id'], ['id'])
84+
batch_op.drop_index('unique_non_deleted_sort_order', postgresql_where=sa.text('is_deleted IS false'))
85+
86+
op.drop_table('inspection_req_enforcement_mappings')
87+
with op.batch_alter_table('inspection_req_enforcement_mappings_version', schema=None) as batch_op:
88+
batch_op.drop_index(batch_op.f('ix_inspection_req_enforcement_mappings_version_transaction_id'))
89+
batch_op.drop_index(batch_op.f('ix_inspection_req_enforcement_mappings_version_operation_type'))
90+
batch_op.drop_index(batch_op.f('ix_inspection_req_enforcement_mappings_version_end_transaction_id'))
91+
92+
op.drop_table('inspection_req_enforcement_mappings_version')
93+
# ### end Alembic commands ###

compliance-api/src/compliance_api/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
33
This module is for the initiation of the flask app.
44
"""
5-
65
import os
6+
# import ssl
77
from http import HTTPStatus
88

99
import secure
@@ -121,6 +121,8 @@ def custom_role_callback(claims):
121121
return claims.get("groups", [])
122122

123123
app_context.config["JWT_ROLE_CALLBACK"] = custom_role_callback
124+
# if os.getenv("FLASK_ENV") == "development":
125+
# ssl._create_default_https_context = ssl._create_unverified_context
124126
jwt_manager.init_app(app_context)
125127

126128

compliance-api/src/compliance_api/models/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
from .inspection import (
2929
Inspection, InspectionAgency, InspectionAttendance, InspectionAttendanceOption, InspectionAttendanceOptionEnum,
3030
InspectionFirstnation, InspectionInitiationOption, InspectionOfficer, InspectionOtherAttendance,
31-
InspectionReqDetailDocument, InspectionReqSourceDetail, InspectionRequirement, InspectionStatusEnum, InspectionType,
32-
InspectionTypeOption, IRStatusOption)
31+
InspectionReqDetailDocument, InspectionReqEnforcementMap, InspectionReqSourceDetail, InspectionRequirement,
32+
InspectionStatusEnum, InspectionType, InspectionTypeOption, IRStatusOption)
3333
from .position import Position
3434
from .project import Project
3535
from .req_source_document_map import RequirementSourceDocumentMap

compliance-api/src/compliance_api/models/inspection/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
InspectionAttendanceOption, InspectionInitiationOption, InspectionTypeOption, IRStatusOption)
1111
from .inspection_other_attendance import InspectionOtherAttendance
1212
from .inspection_req_detail_doc import InspectionReqDetailDocument
13+
from .inspection_req_enforcement_map import InspectionReqEnforcementMap
1314
from .inspection_req_source_detail import InspectionReqSourceDetail
1415
from .inspection_requirement import InspectionRequirement
1516
from .inspection_type import InspectionType

compliance-api/src/compliance_api/models/inspection/inspection_req_detail_doc.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from sqlalchemy.orm import relationship
55

66
from ..base_model import BaseModelVersioned, db
7+
from .inspection_req_source_detail import InspectionReqSourceDetail
78

89

910
class InspectionReqDetailDocument(BaseModelVersioned):
@@ -35,6 +36,9 @@ class InspectionReqDetailDocument(BaseModelVersioned):
3536
nullable=False,
3637
)
3738
document_title = Column(String, nullable=True, comment="The title of the document")
39+
description = Column(
40+
String, nullable=False, comment="The description of the document"
41+
)
3842
section_number = Column(
3943
String,
4044
nullable=True,
@@ -93,3 +97,20 @@ def delete_req_doc_details_by_ids(cls, req_doc_detail_ids, session=None):
9397
session.flush()
9498
else:
9599
db.session.commit()
100+
101+
@classmethod
102+
def delete_by_requirement_id(cls, requirement_id, session=None):
103+
"""Delete requirement doc details by requirement_id."""
104+
requirement_details = (
105+
db.session.query(InspectionReqSourceDetail)
106+
.filter_by(requirement_id=requirement_id, is_deleted=False)
107+
.all()
108+
)
109+
requirement_detail_ids = [detail.id for detail in requirement_details]
110+
cls.query.filter(cls.req_detail_id.in_(requirement_detail_ids)).update(
111+
{cls.is_active: False, cls.is_deleted: True}
112+
)
113+
if session:
114+
session.flush()
115+
else:
116+
db.session.commit()
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""Model for InspectionRequirementEnforcementMapping."""
2+
3+
from sqlalchemy import Column, ForeignKey, Integer
4+
from sqlalchemy.orm import relationship
5+
6+
from ..base_model import BaseModelVersioned, db
7+
8+
9+
class InspectionReqEnforcementMap(BaseModelVersioned):
10+
"""InspectionReqEnforcementMap."""
11+
12+
__tablename__ = "inspection_req_enforcement_mappings"
13+
id = Column(
14+
Integer,
15+
primary_key=True,
16+
autoincrement=True,
17+
comment="The unique identifier",
18+
)
19+
requirement_id = Column(
20+
Integer,
21+
ForeignKey(
22+
"inspection_requirements.id", name="inspection_req_enf_map_req_id_fkey"
23+
),
24+
nullable=False,
25+
comment="The requirement id",
26+
)
27+
enforcement_action_id = Column(
28+
Integer,
29+
ForeignKey(
30+
"enforcement_action_options.id",
31+
name="insepction_req_enf_map_fkey",
32+
),
33+
nullable=True,
34+
comment="The enforcement action taken on the requirement",
35+
)
36+
enforcement_action = relationship(
37+
"EnforcementActionOption", foreign_keys=[enforcement_action_id], lazy="joined"
38+
)
39+
requirement = relationship(
40+
"InspectionRequirement", foreign_keys=[requirement_id], lazy="joined"
41+
)
42+
43+
@classmethod
44+
def get_all_by_requirement_id(cls, requirement_id: int):
45+
"""Retrieve all enforcement_ids by requirement id."""
46+
return cls.query.filter_by(
47+
requirement_id=requirement_id, is_deleted=False, is_active=True
48+
).all()
49+
50+
@classmethod
51+
def bulk_delete(cls, requirement_id: int, enforcement_ids: list[int]):
52+
"""Delete enforcement ids per inspection."""
53+
mappings = cls.query.filter(
54+
cls.requirement_id == requirement_id,
55+
cls.enforcement_action_id.in_(enforcement_ids),
56+
cls.is_active.is_(True),
57+
cls.is_deleted.is_(False),
58+
)
59+
for mapp in mappings:
60+
mapp.update({"is_active": False, "is_deleted": True}, commit=False)
61+
62+
@classmethod
63+
def bulk_insert(cls, requirement_id: int, enforcement_ids: list[int], session=None):
64+
"""Insert enforcement per requirement."""
65+
requirement_enforcement_map = [
66+
InspectionReqEnforcementMap(
67+
**{"requirement_id": requirement_id, "enforcement_action_id": enforcement_id}
68+
)
69+
for enforcement_id in enforcement_ids
70+
]
71+
if session:
72+
session.add_all(requirement_enforcement_map)
73+
session.flush()
74+
else:
75+
db.session.add_all(requirement_enforcement_map)
76+
db.session.commit()

compliance-api/src/compliance_api/models/inspection/inspection_req_source_detail.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,14 @@ def delete_req_details_by_ids(cls, req_detail_ids, session=None):
115115
session.flush()
116116
else:
117117
db.session.commit()
118+
119+
@classmethod
120+
def delete_by_requirement_id(cls, requirement_id, session=None):
121+
"""Delete requirement source details by requirement id."""
122+
cls.query.filter_by(requirement_id=requirement_id, is_deleted=False).update(
123+
{cls.is_active: False, cls.is_deleted: True}
124+
)
125+
if session:
126+
session.flush()
127+
else:
128+
db.session.commit()

compliance-api/src/compliance_api/models/inspection/inspection_requirement.py

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""InspectionRequirement Model."""
22

3-
from sqlalchemy import Column, ForeignKey, Integer, String
3+
from sqlalchemy import Boolean, Column, ForeignKey, Index, Integer, String
44
from sqlalchemy.orm import relationship
55

66
from ..base_model import BaseModelVersioned, db
@@ -30,15 +30,6 @@ class InspectionRequirement(BaseModelVersioned):
3030
nullable=False,
3131
comment="The topic of the requirement",
3232
)
33-
enforcement_action_id = Column(
34-
Integer,
35-
ForeignKey(
36-
"enforcement_action_options.id",
37-
name="insepction_requirements_enforcement_action_fkey",
38-
),
39-
nullable=True,
40-
comment="The enforcement action taken on the requirement",
41-
)
4233
compliance_finding_id = Column(
4334
Integer,
4435
ForeignKey(
@@ -50,12 +41,10 @@ class InspectionRequirement(BaseModelVersioned):
5041
)
5142
findings = Column(String, nullable=True, comment="The findings of the requirement")
5243
sort_order = Column(Integer, nullable=False, comment="The order of requirements")
44+
is_deleted = Column(Boolean, default=False, server_default="f", nullable=False)
5345

5446
inspection = relationship("Inspection", foreign_keys=[inspection_id], lazy="select")
5547
topic = relationship("Topic", foreign_keys=[topic_id], lazy="joined")
56-
enforcement_action = relationship(
57-
"EnforcementActionOption", foreign_keys=[enforcement_action_id], lazy="joined"
58-
)
5948
compliance_finding = relationship(
6049
"ComplianceFindingOption", foreign_keys=[compliance_finding_id], lazy="joined"
6150
)
@@ -64,6 +53,20 @@ class InspectionRequirement(BaseModelVersioned):
6453
back_populates="inspection_requirement",
6554
lazy="select",
6655
)
56+
enforcement_actions = relationship(
57+
"InspectionReqEnforcementMap",
58+
back_populates="requirement",
59+
lazy="select"
60+
)
61+
__table_args__ = (
62+
Index(
63+
"unique_non_deleted_sort_order", # Index name
64+
"inspection_id",
65+
"sort_order",
66+
unique=True,
67+
postgresql_where=(is_deleted.is_(False)), # Condition for uniqueness
68+
),
69+
)
6770

6871
@classmethod
6972
def create_requirement(cls, requirement_obj, session=None):
@@ -76,12 +79,26 @@ def create_requirement(cls, requirement_obj, session=None):
7679
requirement.save()
7780
return requirement
7881

82+
@classmethod
83+
def delete_requirement(cls, requirement_id, session=None):
84+
"""Delete the requirement."""
85+
requirement = cls.find_by_id(requirement_id)
86+
if not requirement:
87+
return None
88+
requirement.update({"is_active": False, "is_deleted": True}, commit=False)
89+
if session:
90+
session.flush()
91+
else:
92+
db.session.commit()
93+
return requirement
94+
7995
@classmethod
8096
def get_by_inspection_id(cls, inspection_id):
8197
"""Get requirements by inspection id."""
8298
return (
8399
db.session.query(InspectionRequirement)
84100
.filter_by(inspection_id=inspection_id, is_deleted=False, is_active=True)
101+
.order_by(cls.sort_order)
85102
.all()
86103
)
87104

0 commit comments

Comments
 (0)