Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
from app.routes.goal_routes import bp as goals_bp
import os

from dotenv import load_dotenv
load_dotenv()

def create_app(config=None):
app = Flask(__name__)
Expand Down
4 changes: 2 additions & 2 deletions app/models/goal.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from sqlalchemy.orm import Mapped, mapped_column,relationship
from sqlalchemy.orm import Mapped, mapped_column, relationship
from ..db import db
from sqlalchemy import String
#from sqlalchemy import Date



class Goal(db.Model):
Expand Down
2 changes: 0 additions & 2 deletions app/models/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ def to_dict(self): # json

return task_dict



@classmethod
def from_dict(cls, data_dict):
if "title" not in data_dict:
Expand Down
49 changes: 25 additions & 24 deletions app/routes/goal_routes.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from flask import Blueprint, jsonify, request, abort, make_response
from flask import Blueprint, request, abort, make_response,Response
from ..db import db
from ..models.goal import Goal
from ..models.task import Task
from .route_utilities import validate_model
from .route_utilities import validate_model,create_model,get_models_with_filters


bp = Blueprint("goals_bp", __name__, url_prefix="/goals")
Expand All @@ -12,27 +12,27 @@
@bp.post("")
def create_goal():
request_body = request.get_json()
try:
new_goal = Goal.from_dict(request_body)
except KeyError:
return jsonify({"details": "Invalid data"}), 400
# try:
# new_goal = Goal.from_dict(request_body)
# except KeyError:
# return jsonify({"details": "Invalid data"}), 400

db.session.add(new_goal)
db.session.commit()
# db.session.add(new_goal)
# db.session.commit()

return jsonify(new_goal.to_dict()), 201
#return jsonify(new_goal.to_dict()), 201
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As part of these updates, please follow best practices to remove the old code once the refactor is working as expected.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure!

return create_model(Goal,request_body)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice update to use create_model for the Goal class! Is there a reason we cannot use it for Tasks as well?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just updated



@bp.get("")
def get_all_goals():
goals = Goal.query.order_by(Goal.id).all()
return jsonify([goal.to_dict() for goal in goals]), 200

filters = request.args.to_dict()
return get_models_with_filters(Goal,filters)

@bp.get("/<id>")
def get_one_goal(id):
goal = validate_model(Goal, id)
return jsonify(goal.to_dict()), 200
return goal.to_dict()



Expand All @@ -45,7 +45,7 @@ def update_goal(id):
goal.title = request_body["title"]

db.session.commit()
return jsonify(goal.to_dict()), 200
return goal.to_dict()



Expand All @@ -56,8 +56,8 @@ def delete_goal(id):
db.session.delete(goal)
db.session.commit()

return jsonify({"message": f'Goal {goal.id} successfully deleted'}), 204

#return jsonify({"message": f'Goal {goal.id} successfully deleted'}), 204
return Response(status=204, mimetype="application/json")

#nested
@bp.post("/<goal_id>/tasks")
Expand All @@ -70,18 +70,16 @@ def add_tasks_to_goal(goal_id):
for task in goal.tasks:
task.goal_id = None



for task_id in task_ids:
task = validate_model(Task, task_id)
task.goal_id = goal.id

db.session.commit()

return jsonify({
return {
"id": goal.id,
"task_ids": task_ids
}), 200
}, 200



Expand All @@ -91,10 +89,13 @@ def get_tasks_for_goal(goal_id):

tasks_response = [task.to_dict() for task in goal.tasks]

goal_dict = goal.to_dict()
goal_dict["tasks"] = tasks_response

return jsonify(goal_dict), 200
response_body = {
"id": goal.id,
"title": goal.title,
"tasks": tasks_response
}

return response_body,200



30 changes: 4 additions & 26 deletions app/routes/task_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ def create_task():
db.session.commit()
return new_task.to_dict(), 201


@bp.get("")

def get_all_tasks():
query = db.select(Task)

Expand Down Expand Up @@ -63,76 +61,56 @@ def get_all_tasks():

result_list =[task.to_dict()for task in tasks]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small spacing issue

Suggested change
result_list =[task.to_dict()for task in tasks]
result_list =[task.to_dict() for task in tasks]


return jsonify(result_list or []),200

return result_list or []

@bp.get("/<id>")

def get_one_task(id):
Comment on lines +56 to +57
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blank line between decorator and function it is acting on.

Suggested change
@bp.get("/<id>")
def get_one_task(id):
@bp.get("/<id>")
def get_one_task(id):


task =validate_model(Task,id)
return task.to_dict()


@bp.put("/<id>")
def replace_task(id):
task = validate_model(Task, id)

request_body = request.get_json()

# if request_body["is_complete"]:
# task.completed_at = datetime.utcnow()
# else:
# task.completed_at = None
task.title = request_body["title"]

task.description = request_body["description"]

db.session.commit()

return Response(status = 204,mimetype ="application/json")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small spacing issues.

We don't include spaces around the = when we are filling out a keyword argument in a function invocation.

  • This differs from when it is used for variable assignment or as part of a comparison operator where we always surround = in spaces.
Suggested change
return Response(status = 204,mimetype ="application/json")
return Response(status=204, mimetype="application/json")


Copy link
Copy Markdown
Contributor

@kelsey-steven-ada kelsey-steven-ada Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spacing between and inside of functions is inconsistent across the file. I would like to see this revisited if you are already working in this file.

This is something that will come up in code reviews in engineering teams, code style is important to readability. This is something we need to work into our review process for ourselves before we open pull requests.

@bp.delete("/<id>")
def del_task(id):
task = validate_model(Task, id)

db.session.delete(task)

db.session.commit()

return Response(status = 204,mimetype ="application/json")




# @bp.patch("/<id>/mark_complete")
# def mark_complete(id):
# task = validate_model(Task, id)
# task.completed_at = datetime.utcnow()
# db.session.commit()
# return Response(status=204, mimetype="application/json")


@bp.patch("/<id>/mark_incomplete")
def mark_incomplete(id):
task = validate_model(Task, id)

task.completed_at = None
db.session.commit()
return Response(status=204, mimetype="application/json")



@bp.patch("/<id>/mark_complete")
def mark_task_complete(id):
task = validate_model(Task, id)
#task = Task.query.get(id)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove commented code



task.completed_at = datetime.now(timezone.utc)
db.session.commit()


slack_token = os.environ.get("SLACK_BOT_TOKEN")
slack_channel = os.environ.get("SLACK_CHANNEL", "#test_task_slack_api")
message = f"Task *{task.title}* has been completed!"
Expand All @@ -144,8 +122,8 @@ def mark_task_complete(id):

json={"channel": slack_channel, "text": message}
)
if current_app.config.get("TESTING"):
return Response(status=204, mimetype="application/json")
#if current_app.config.get("TESTING"):
return Response(status=204, mimetype="application/json")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice restructuring so the message is only sent in production mode, but we always return the same response.



return jsonify({"task": task.to_dict()}), 200

12 changes: 12 additions & 0 deletions tests/test_wave_07.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,15 @@ def test_route_utilities_create_model_with_goal_missing_title(client):
# *****************************************************************************
# **Complete test with assertion about status code response body***************
# *****************************************************************************



def test_mark_complete_response_consistency(client, one_task):
response = client.patch("/tasks/1/mark_complete")

#print("Test mode response status:", response.status_code)
#print("Test mode response mimetype:", response.mimetype)
#print("Test mode response data:", response.get_data(as_text=True))

assert response.status_code == 204
assert response.mimetype == "application/json"