Skip to content

Commit

Permalink
Merge pull request #42 from VineetBala-AOT/main
Browse files Browse the repository at this point in the history
Edit or Approve Condition Number and Name
  • Loading branch information
VineetBala-AOT authored Jan 13, 2025
2 parents aae9900 + bec5418 commit 7168a2a
Show file tree
Hide file tree
Showing 13 changed files with 438 additions and 327 deletions.
19 changes: 12 additions & 7 deletions condition-api/src/condition_api/resources/condition.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"""API endpoints for managing a condition resource."""

from http import HTTPStatus
from flask import request
from flask_restx import Namespace, Resource, cors
from marshmallow import ValidationError

Expand All @@ -35,7 +36,7 @@
)

@cors_preflight("GET, OPTIONS, PATCH")
@API.route("/project/<string:project_id>/document/<string:document_id>/condition/<int:condition_number>", methods=["PATCH", "GET", "OPTIONS"])
@API.route("/project/<string:project_id>/document/<string:document_id>/condition/<int:condition_id>", methods=["PATCH", "GET", "OPTIONS"])
class ConditionDetailsResource(Resource):
"""Resource for fetching condition details by project_id."""

Expand All @@ -45,10 +46,10 @@ class ConditionDetailsResource(Resource):
@API.response(HTTPStatus.BAD_REQUEST, "Bad Request")
@auth.require
@cors.crossdomain(origin="*")
def get(project_id, document_id, condition_number):
def get(project_id, document_id, condition_id):
"""Fetch conditions and condition attributes by project ID."""
try:
condition_details = ConditionService.get_condition_details(project_id, document_id, condition_number)
condition_details = ConditionService.get_condition_details(project_id, document_id, condition_id)
if not condition_details:
return {"message": "Condition not found"}, HTTPStatus.NOT_FOUND

Expand All @@ -68,12 +69,12 @@ def get(project_id, document_id, condition_number):
@API.response(HTTPStatus.BAD_REQUEST, "Bad Request")
@cors.crossdomain(origin="*")
@auth.require
def patch(project_id, document_id, condition_number):
def patch(project_id, document_id, condition_id):
"""Edit condition data."""
try:
conditions_data = ConditionSchema().load(API.payload)
updated_condition = ConditionService.update_condition(
conditions_data, project_id, document_id, condition_number)
conditions_data, project_id, document_id, condition_id, False)
return ConditionSchema().dump(updated_condition), HTTPStatus.OK
except ValidationError as err:
return {"message": str(err)}, HTTPStatus.BAD_REQUEST
Expand All @@ -93,7 +94,11 @@ class ConditionDetailResource(Resource):
def get(project_id, document_id):
"""Fetch conditions and condition attributes by project ID."""
try:
condition_details = ConditionService.get_all_conditions(project_id, document_id)
query_params = request.args
include_condition_attributes = query_params.get('include_condition_attributes', '', type=str)
include_nested_conditions = query_params.get('include_subconditions', '', type=str)
condition_details = ConditionService.get_all_conditions(
project_id, document_id, include_condition_attributes, include_nested_conditions)
if not condition_details:
return {}
# Instantiate the schema
Expand Down Expand Up @@ -162,7 +167,7 @@ def patch(condition_id):
"""Edit condition data."""
try:
conditions_data = ConditionSchema().load(API.payload)
updated_condition = ConditionService.update_condition(conditions_data, None, None, None, condition_id)
updated_condition = ConditionService.update_condition(conditions_data, None, None, condition_id, True)
return ConditionSchema().dump(updated_condition), HTTPStatus.OK
except ValidationError as err:
return {"message": str(err)}, HTTPStatus.BAD_REQUEST
Expand Down
178 changes: 90 additions & 88 deletions condition-api/src/condition_api/services/condition_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ConditionService:
"""Service for managing condition-related operations."""

@staticmethod
def get_condition_details(project_id, document_id, condition_number):
def get_condition_details(project_id, document_id, condition_id):
"""Fetch condition details along with related condition attributes by project ID."""

# Aliases for the tables
Expand Down Expand Up @@ -98,7 +98,7 @@ def get_condition_details(project_id, document_id, condition_number):
(conditions.amended_document_id.is_(None))
)
)
& (conditions.condition_number == condition_number)
& (conditions.id == condition_id)
)
.order_by(subconditions.id)
.all()
Expand Down Expand Up @@ -192,7 +192,12 @@ def get_condition_details(project_id, document_id, condition_number):
}

@staticmethod
def get_all_conditions(project_id, document_id):
def get_all_conditions(
project_id,
document_id,
include_condition_attributes=False,
include_nested_conditions=False
):
"""Fetch all conditions and their related subconditions by project ID and document ID."""

# Aliases for the tables
Expand All @@ -204,33 +209,18 @@ def get_all_conditions(project_id, document_id):
conditions = aliased(Condition)
subconditions = aliased(Subcondition)

amendment_subquery = (
db.session.query(
conditions.condition_number,
func.string_agg(amendments.amendment_name.distinct(), ', ').label('amendment_names')
)
.join(conditions, conditions.amended_document_id == amendments.amended_document_id) # Join amendments to conditions
.join(documents, conditions.document_id == documents.document_id) # Join conditions to documents
.join(projects, projects.project_id == documents.project_id) # Join documents to projects
.filter(
(projects.project_id == project_id) & (documents.document_id == document_id)
)
.group_by(conditions.condition_number)
.subquery()
)

# Check if the document_id exists in the amendments table
amendment_exists = (
# Check if the document_id is an amendment
is_amendment_document = (
db.session.query(amendments.document_id, amendments.amended_document_id)
.filter(amendments.amended_document_id == document_id)
.first()
)

if amendment_exists:
if is_amendment_document:
# Join conditions to amendments instead of documents
amendment_label_subquery = (
db.session.query(amendments.amendment_name)
.filter(amendments.amended_document_id == amendment_exists[1])
.filter(amendments.amended_document_id == is_amendment_document[1])
.subquery()
)
document_label_query = amendment_label_subquery.c.amendment_name.label("document_label")
Expand All @@ -239,10 +229,28 @@ def get_all_conditions(project_id, document_id):
document_type_join = (amendments.document_type_id == document_types.id)
else:
# Join conditions directly to documents
condition_join = documents.document_id == conditions.document_id
condition_join = and_(
documents.document_id == conditions.document_id,
conditions.amended_document_id.is_(None)
)
document_label_query = documents.document_label
date_issued_query = extract("year", documents.date_issued).label("year_issued")
document_type_join = (documents.document_type_id == document_types.id)
document_type_join = documents.document_type_id == document_types.id

amendment_subquery = (
db.session.query(
conditions.condition_number,
func.string_agg(amendments.amendment_name.distinct(), ', ').label('amendment_names')
)
.join(conditions, conditions.amended_document_id == amendments.amended_document_id) # Join amendments to conditions
.join(documents, conditions.document_id == documents.document_id) # Join conditions to documents
.join(projects, projects.project_id == documents.project_id) # Join documents to projects
.filter(
(projects.project_id == project_id) & (documents.document_id == document_id)
)
.group_by(conditions.condition_number)
.subquery()
)

# Query for all conditions and their related subconditions and attributes
condition_data = (
Expand All @@ -258,12 +266,12 @@ def get_all_conditions(project_id, document_id):
conditions.topic_tags,
conditions.subtopic_tags,
amendment_subquery.c.amendment_names,
subconditions.id.label('subcondition_id'),
subconditions.subcondition_identifier,
subconditions.subcondition_text,
subconditions.parent_subcondition_id,
date_issued_query
)
.outerjoin(
conditions,
condition_join
)
.outerjoin(
document_types,
document_type_join
Expand All @@ -272,22 +280,14 @@ def get_all_conditions(project_id, document_id):
document_categories,
document_categories.id == document_types.document_category_id
)
.outerjoin(
conditions,
condition_join
)
.outerjoin(
subconditions,
conditions.id == subconditions.condition_id,
)
.outerjoin(
amendment_subquery,
conditions.condition_number == amendment_subquery.c.condition_number
)
.filter(
(
(amendments.amended_document_id == amendment_exists[1])
if amendment_exists
(amendments.amended_document_id == is_amendment_document[1])
if is_amendment_document
else (documents.document_id == document_id and conditions.amended_document_id is None)
)
)
Expand All @@ -307,10 +307,6 @@ def get_all_conditions(project_id, document_id):
conditions.is_approved,
conditions.topic_tags,
conditions.subtopic_tags,
subconditions.id,
subconditions.subcondition_identifier,
subconditions.subcondition_text,
subconditions.parent_subcondition_id,
amendment_subquery.c.amendment_names,
date_issued_query,
document_label_query
Expand All @@ -335,42 +331,52 @@ def get_all_conditions(project_id, document_id):

# Process the query result
for row in condition_data:
cond_num = row.condition_number
cond_id = row.condition_id

# Add each condition to the map if not already present
if cond_num not in conditions_map:
conditions_map[cond_num] = {
"condition_id": row.condition_id,
"condition_name": row.condition_name,
"condition_number": row.condition_number,
"condition_text": row.condition_text,
"is_approved": row.is_approved,
"topic_tags": row.topic_tags,
"subtopic_tags": row.subtopic_tags,
"amendment_names": row.amendment_names,
"year_issued": row.year_issued,
"condition_attributes": [],
"subconditions": []
}

# Handle subconditions
subcond_id = row.subcondition_id
if subcond_id:
subcondition = {
"subcondition_identifier": row.subcondition_identifier,
"subcondition_text": row.subcondition_text,
"subconditions": []
}
subcondition_map[subcond_id] = subcondition

# If the subcondition has a parent, append it to the parent's subcondition list
if row.parent_subcondition_id:
parent = subcondition_map.get(row.parent_subcondition_id)
if parent:
parent["subconditions"].append(subcondition)
else:
# Top-level subcondition for this condition
conditions_map[cond_num]["subconditions"].append(subcondition)
conditions_map[cond_id] = {
"condition_id": row.condition_id,
"condition_name": row.condition_name,
"condition_number": row.condition_number,
"condition_text": row.condition_text,
"is_approved": row.is_approved,
"topic_tags": row.topic_tags,
"subtopic_tags": row.subtopic_tags,
"amendment_names": row.amendment_names,
"year_issued": row.year_issued,
"condition_attributes": [],
"subconditions": []
}

if include_nested_conditions:
subconditions_data = (
db.session.query(
subconditions.id.label('subcondition_id'),
subconditions.subcondition_identifier,
subconditions.subcondition_text,
subconditions.parent_subcondition_id
)
.filter(subconditions.condition_id == cond_id)
)
for row in subconditions_data:
# Handle subconditions
subcond_id = row.subcondition_id
if subcond_id:
subcondition = {
"subcondition_identifier": row.subcondition_identifier,
"subcondition_text": row.subcondition_text,
"subconditions": []
}
subcondition_map[subcond_id] = subcondition

# If the subcondition has a parent, append it to the parent's subcondition list
if row.parent_subcondition_id:
parent = subcondition_map.get(row.parent_subcondition_id)
if parent:
parent["subconditions"].append(subcondition)
else:
# Top-level subcondition for this condition
conditions_map[cond_id]["subconditions"].append(subcondition)

# Return all conditions
return {
Expand All @@ -381,23 +387,21 @@ def get_all_conditions(project_id, document_id):
"conditions": list(conditions_map.values())
}


@staticmethod
def update_condition(
conditions_data,
project_id=None,
document_id=None,
condition_number=None,
condition_id=None,
check_condition_exists=None,
):
"""
Update the approved status, topic tags, and subconditions of a specific condition.
This method accepts either:
1. project_id, document_id, and condition_number, or
2. condition_id as input.
1. project_id, document_id, and condition_id as input.
"""
if condition_id:
if check_condition_exists:
# Query by condition_id
condition = db.session.query(Condition).filter_by(id=condition_id).first()

Expand All @@ -420,7 +424,7 @@ def update_condition(
if conditions_data.get("condition_number") in existing_condition_numbers:
raise ValueError("This condition number already exists. Please enter a new one.")

elif project_id and document_id and condition_number:
else:
amendment = (
db.session.query(Amendment.amended_document_id)
.filter(Amendment.amended_document_id == document_id)
Expand All @@ -431,16 +435,14 @@ def update_condition(
condition = db.session.query(Condition).filter_by(
project_id=project_id,
amended_document_id=amendment[0],
condition_number=condition_number
id=condition_id
).first()
else:
condition = db.session.query(Condition).filter_by(
project_id=project_id,
document_id=document_id,
condition_number=condition_number
id=condition_id
).first()
else:
raise ValueError("You must provide either condition_id or project_id, document_id, and condition_number.")

if any(key for key in conditions_data.keys() if key != "subconditions"):
ConditionService._update_from_dict(condition, conditions_data)
Expand All @@ -451,11 +453,11 @@ def update_condition(
if isinstance(subcond["subcondition_id"], str) and "-" not in subcond["subcondition_id"]
]
db.session.query(Subcondition).filter(
Subcondition.condition_id == condition.id,
Subcondition.condition_id == condition_id,
Subcondition.id.notin_(existing_subcondition_ids)
).delete(synchronize_session=False)
ConditionService.upsert_subconditions(
condition.id, conditions_data.get("subconditions"), None)
condition_id, conditions_data.get("subconditions"), None)

condition.commit()
return condition
Expand Down
Loading

0 comments on commit 7168a2a

Please sign in to comment.