round 3
This commit is contained in:
169
api/child_api.py
169
api/child_api.py
@@ -4,6 +4,16 @@ from db.db import child_db, task_db, reward_db
|
||||
from api.reward_status import RewardStatus
|
||||
from api.child_tasks import ChildTask
|
||||
from api.child_rewards import ChildReward
|
||||
from events.sse import send_to_user, send_event_to_user
|
||||
from events.types.child_add import ChildAdd
|
||||
from events.types.child_delete import ChildDelete
|
||||
from events.types.child_update import ChildUpdate
|
||||
from events.types.event import Event
|
||||
from events.types.event_types import EventType
|
||||
from events.types.reward_set import RewardSet
|
||||
from events.types.reward_update import RewardUpdate
|
||||
from events.types.task_set import TaskSet
|
||||
from events.types.task_update import TaskUpdate
|
||||
|
||||
from models.child import Child
|
||||
from models.task import Task
|
||||
@@ -31,8 +41,9 @@ def add_child():
|
||||
if not image:
|
||||
image = 'boy01'
|
||||
|
||||
child = Child(name, age, image_id=image)
|
||||
child = Child(name=name, age=age, image_id=image)
|
||||
child_db.insert(child.to_dict())
|
||||
send_event_to_user("user123", Event(EventType.CHILD_ADD.value, ChildAdd(child.id, "set")))
|
||||
return jsonify({'message': f'Child {name} added.'}), 201
|
||||
|
||||
@child_api.route('/child/<id>/edit', methods=['PUT'])
|
||||
@@ -56,6 +67,7 @@ def edit_child(id):
|
||||
if image is not None:
|
||||
child['image_id'] = image
|
||||
child_db.update(child, ChildQuery.id == id)
|
||||
send_event_to_user("user123", Event(EventType.CHILD_UPDATE.value, ChildUpdate(id, "set")))
|
||||
return jsonify({'message': f'Child {id} updated.'}), 200
|
||||
|
||||
@child_api.route('/child/list', methods=['GET'])
|
||||
@@ -68,6 +80,8 @@ def list_children():
|
||||
def delete_child(id):
|
||||
ChildQuery = Query()
|
||||
if child_db.remove(ChildQuery.id == id):
|
||||
send_event_to_user("user123",
|
||||
Event(EventType.CHILD_DELETE.value, ChildDelete(id, "deleted")))
|
||||
return jsonify({'message': f'Child {id} deleted.'}), 200
|
||||
return jsonify({'error': 'Child not found'}), 404
|
||||
|
||||
@@ -89,6 +103,37 @@ def assign_task_to_child(id):
|
||||
child_db.update({'tasks': child['tasks']}, ChildQuery.id == id)
|
||||
return jsonify({'message': f'Task {task_id} assigned to {child['name']}.'}), 200
|
||||
|
||||
# python
|
||||
@child_api.route('/child/<id>/set-tasks', methods=['PUT'])
|
||||
def set_child_tasks(id):
|
||||
data = request.get_json() or {}
|
||||
task_ids = data.get('task_ids')
|
||||
if not isinstance(task_ids, list):
|
||||
return jsonify({'error': 'task_ids must be a list'}), 400
|
||||
|
||||
# Deduplicate and drop falsy values
|
||||
new_task_ids = [tid for tid in dict.fromkeys(task_ids) if tid]
|
||||
|
||||
ChildQuery = Query()
|
||||
result = child_db.search(ChildQuery.id == id)
|
||||
if not result:
|
||||
return jsonify({'error': 'Child not found'}), 404
|
||||
|
||||
# Optional: validate task IDs exist in the task DB
|
||||
TaskQuery = Query()
|
||||
valid_task_ids = []
|
||||
for tid in new_task_ids:
|
||||
if task_db.get(TaskQuery.id == tid):
|
||||
valid_task_ids.append(tid)
|
||||
# Replace tasks with validated IDs
|
||||
child_db.update({'tasks': valid_task_ids}, ChildQuery.id == id)
|
||||
send_event_to_user("user123", Event(EventType.TASK_SET.value, TaskSet(id, "set")))
|
||||
return jsonify({
|
||||
'message': f'Tasks set for child {id}.',
|
||||
'task_ids': valid_task_ids,
|
||||
'count': len(valid_task_ids)
|
||||
}), 200
|
||||
|
||||
|
||||
|
||||
@child_api.route('/child/<id>/remove-task', methods=['POST'])
|
||||
@@ -159,6 +204,48 @@ def list_assignable_tasks(id):
|
||||
|
||||
return jsonify({'tasks': assignable_tasks, 'count': len(assignable_tasks)}), 200
|
||||
|
||||
|
||||
@child_api.route('/child/<id>/list-all-tasks', methods=['GET'])
|
||||
def list_all_tasks(id):
|
||||
ChildQuery = Query()
|
||||
result = child_db.search(ChildQuery.id == id)
|
||||
if not result:
|
||||
return jsonify({'error': 'Child not found'}), 404
|
||||
|
||||
child = result[0]
|
||||
assigned_ids = set(child.get('tasks', []))
|
||||
|
||||
# Get all tasks from database
|
||||
all_tasks = task_db.all()
|
||||
|
||||
assigned_tasks = []
|
||||
assignable_tasks = []
|
||||
|
||||
for task in all_tasks:
|
||||
if not task or not task.get('id'):
|
||||
continue
|
||||
|
||||
ct = ChildTask(
|
||||
task.get('name'),
|
||||
task.get('is_good'),
|
||||
task.get('points'),
|
||||
task.get('image_id'),
|
||||
task.get('id')
|
||||
)
|
||||
|
||||
if task.get('id') in assigned_ids:
|
||||
assigned_tasks.append(ct.to_dict())
|
||||
else:
|
||||
assignable_tasks.append(ct.to_dict())
|
||||
|
||||
return jsonify({
|
||||
'assigned_tasks': assigned_tasks,
|
||||
'assignable_tasks': assignable_tasks,
|
||||
'assigned_count': len(assigned_tasks),
|
||||
'assignable_count': len(assignable_tasks)
|
||||
}), 200
|
||||
|
||||
|
||||
@child_api.route('/child/<id>/trigger-task', methods=['POST'])
|
||||
def trigger_child_task(id):
|
||||
data = request.get_json()
|
||||
@@ -188,6 +275,7 @@ def trigger_child_task(id):
|
||||
child.points = max(child.points, 0)
|
||||
# update the child in the database
|
||||
child_db.update({'points': child.points}, ChildQuery.id == id)
|
||||
send_event_to_user("user123", Event(EventType.TASK_UPDATE.value, TaskUpdate(task.id, child.id,"complete", child.points)))
|
||||
|
||||
return jsonify({'message': f'{task.name} points assigned to {child.name}.', 'points': child.points, 'id': child.id}), 200
|
||||
|
||||
@@ -209,6 +297,78 @@ def assign_reward_to_child(id):
|
||||
child_db.update({'rewards': child['rewards']}, ChildQuery.id == id)
|
||||
return jsonify({'message': f'Reward {reward_id} assigned to {child["name"]}.'}), 200
|
||||
|
||||
@child_api.route('/child/<id>/list-all-rewards', methods=['GET'])
|
||||
def list_all_rewards(id):
|
||||
ChildQuery = Query()
|
||||
result = child_db.search(ChildQuery.id == id)
|
||||
if not result:
|
||||
return jsonify({'error': 'Child not found'}), 404
|
||||
|
||||
child = result[0]
|
||||
assigned_ids = set(child.get('rewards', []))
|
||||
|
||||
# Get all rewards from database
|
||||
all_rewards = reward_db.all()
|
||||
|
||||
assigned_rewards = []
|
||||
assignable_rewards = []
|
||||
|
||||
for reward in all_rewards:
|
||||
if not reward or not reward.get('id'):
|
||||
continue
|
||||
|
||||
cr = ChildReward(
|
||||
reward.get('name'),
|
||||
reward.get('cost'),
|
||||
reward.get('image_id'),
|
||||
reward.get('id')
|
||||
)
|
||||
|
||||
if reward.get('id') in assigned_ids:
|
||||
assigned_rewards.append(cr.to_dict())
|
||||
else:
|
||||
assignable_rewards.append(cr.to_dict())
|
||||
|
||||
return jsonify({
|
||||
'assigned_rewards': assigned_rewards,
|
||||
'assignable_rewards': assignable_rewards,
|
||||
'assigned_count': len(assigned_rewards),
|
||||
'assignable_count': len(assignable_rewards)
|
||||
}), 200
|
||||
|
||||
|
||||
@child_api.route('/child/<id>/set-rewards', methods=['PUT'])
|
||||
def set_child_rewards(id):
|
||||
data = request.get_json() or {}
|
||||
reward_ids = data.get('reward_ids')
|
||||
if not isinstance(reward_ids, list):
|
||||
return jsonify({'error': 'reward_ids must be a list'}), 400
|
||||
|
||||
# Deduplicate and drop falsy values
|
||||
new_reward_ids = [rid for rid in dict.fromkeys(reward_ids) if rid]
|
||||
|
||||
ChildQuery = Query()
|
||||
result = child_db.search(ChildQuery.id == id)
|
||||
if not result:
|
||||
return jsonify({'error': 'Child not found'}), 404
|
||||
|
||||
# Optional: validate reward IDs exist in the reward DB
|
||||
RewardQuery = Query()
|
||||
valid_reward_ids = []
|
||||
for rid in new_reward_ids:
|
||||
if reward_db.get(RewardQuery.id == rid):
|
||||
valid_reward_ids.append(rid)
|
||||
|
||||
# Replace rewards with validated IDs
|
||||
child_db.update({'rewards': valid_reward_ids}, ChildQuery.id == id)
|
||||
send_event_to_user("user123", Event(EventType.REWARD_SET.value, RewardSet(id, "set")))
|
||||
return jsonify({
|
||||
'message': f'Rewards set for child {id}.',
|
||||
'reward_ids': valid_reward_ids,
|
||||
'count': len(valid_reward_ids)
|
||||
}), 200
|
||||
|
||||
|
||||
@child_api.route('/child/<id>/remove-reward', methods=['POST'])
|
||||
def remove_reward_from_child(id):
|
||||
data = request.get_json()
|
||||
@@ -298,6 +458,7 @@ def trigger_child_reward(id):
|
||||
child.points -= reward.cost
|
||||
# update the child in the database
|
||||
child_db.update({'points': child.points}, ChildQuery.id == id)
|
||||
send_event_to_user("user123", Event(EventType.REWARD_UPDATE.value, RewardUpdate(reward.id, child.id, "redeemed", child.points)))
|
||||
return jsonify({'message': f'{reward.name} assigned to {child.name}.', 'points': child.points, 'id': child.id}), 200
|
||||
|
||||
@child_api.route('/child/<id>/affordable-rewards', methods=['GET'])
|
||||
@@ -331,11 +492,11 @@ def reward_status(id):
|
||||
RewardQuery = Query()
|
||||
statuses = []
|
||||
for reward_id in reward_ids:
|
||||
reward = reward_db.get(RewardQuery.id == reward_id)
|
||||
reward: Reward = Reward.from_dict(reward_db.get(RewardQuery.id == reward_id))
|
||||
if not reward:
|
||||
continue
|
||||
points_needed = max(0, reward.get('cost', 0) - points)
|
||||
status = RewardStatus(reward.get('id'), reward.get('name'), points_needed, reward.get('image_id'))
|
||||
points_needed = max(0, reward.cost - points)
|
||||
status = RewardStatus(reward.id, reward.name, points_needed, reward.cost, reward.image_id)
|
||||
statuses.append(status.to_dict())
|
||||
|
||||
statuses.sort(key=lambda s: s['points_needed'])
|
||||
|
||||
@@ -61,8 +61,8 @@ def upload():
|
||||
format_extension_map = {'JPEG': '.jpg', 'PNG': '.png'}
|
||||
extension = format_extension_map.get(original_format, '.png')
|
||||
|
||||
_id = str(uuid.uuid4())
|
||||
filename = _id + extension
|
||||
image_record = Image(extension=extension, permanent=perm, type=image_type)
|
||||
filename = image_record.id + extension
|
||||
filepath = os.path.abspath(os.path.join(UPLOAD_FOLDER, filename))
|
||||
|
||||
try:
|
||||
@@ -76,10 +76,9 @@ def upload():
|
||||
except Exception:
|
||||
return jsonify({'error': 'Failed to save processed image'}), 500
|
||||
|
||||
image_record = Image(image_type, extension, permanent=perm, id=_id)
|
||||
image_db.insert(image_record.to_dict())
|
||||
|
||||
return jsonify({'message': 'Image uploaded successfully', 'filename': filename, 'id': _id}), 200
|
||||
return jsonify({'message': 'Image uploaded successfully', 'filename': filename, 'id': image_record.id}), 200
|
||||
|
||||
@image_api.route('/image/request/<id>', methods=['GET'])
|
||||
def request_image(id):
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
from flask import Blueprint, request, jsonify
|
||||
from tinydb import Query
|
||||
|
||||
from events.sse import send_event_to_user
|
||||
from events.types.event import Event
|
||||
from events.types.event_types import EventType
|
||||
from events.types.reward_created import RewardCreated
|
||||
from events.types.reward_deleted import RewardDeleted
|
||||
from events.types.reward_edited import RewardEdited
|
||||
from models.reward import Reward
|
||||
from db.db import reward_db, child_db
|
||||
|
||||
@@ -15,8 +22,11 @@ def add_reward():
|
||||
image = data.get('image_id', '')
|
||||
if not name or description is None or cost is None:
|
||||
return jsonify({'error': 'Name, description, and cost are required'}), 400
|
||||
reward = Reward(name, description, cost, image_id=image)
|
||||
reward = Reward(name=name, description=description, cost=cost, image_id=image)
|
||||
reward_db.insert(reward.to_dict())
|
||||
send_event_to_user("user123", Event(EventType.REWARD_CREATED.value,
|
||||
RewardCreated(reward.id, "created")))
|
||||
|
||||
return jsonify({'message': f'Reward {name} added.'}), 201
|
||||
|
||||
|
||||
@@ -46,6 +56,9 @@ def delete_reward(id):
|
||||
if id in rewards:
|
||||
rewards.remove(id)
|
||||
child_db.update({'rewards': rewards}, ChildQuery.id == child.get('id'))
|
||||
send_event_to_user("user123", Event(EventType.REWARD_DELETED.value,
|
||||
RewardDeleted(id, "created")))
|
||||
|
||||
return jsonify({'message': f'Reward {id} deleted.'}), 200
|
||||
return jsonify({'error': 'Reward not found'}), 404
|
||||
|
||||
@@ -87,4 +100,7 @@ def edit_reward(id):
|
||||
|
||||
reward_db.update(updates, RewardQuery.id == id)
|
||||
updated = reward_db.get(RewardQuery.id == id)
|
||||
send_event_to_user("user123", Event(EventType.REWARD_EDITED.value,
|
||||
RewardEdited(id, "created")))
|
||||
|
||||
return jsonify(updated), 200
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
class RewardStatus:
|
||||
def __init__(self, id, name, points_needed, image_id):
|
||||
def __init__(self, id, name, points_needed, cost, image_id):
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.points_needed = points_needed
|
||||
self.cost = cost
|
||||
self.image_id = image_id
|
||||
|
||||
def to_dict(self):
|
||||
@@ -10,5 +11,6 @@ class RewardStatus:
|
||||
'id': self.id,
|
||||
'name': self.name,
|
||||
'points_needed': self.points_needed,
|
||||
'cost': self.cost,
|
||||
'image_id': self.image_id
|
||||
}
|
||||
@@ -1,5 +1,12 @@
|
||||
from flask import Blueprint, request, jsonify
|
||||
from tinydb import Query
|
||||
|
||||
from events.sse import send_event_to_user
|
||||
from events.types.event import Event
|
||||
from events.types.event_types import EventType
|
||||
from events.types.task_created import TaskCreated
|
||||
from events.types.task_deleted import TaskDeleted
|
||||
from events.types.task_edited import TaskEdited
|
||||
from models.task import Task
|
||||
from db.db import task_db, child_db
|
||||
|
||||
@@ -15,8 +22,10 @@ def add_task():
|
||||
image = data.get('image_id', '')
|
||||
if not name or points is None or is_good is None:
|
||||
return jsonify({'error': 'Name, points, and is_good are required'}), 400
|
||||
task = Task(name, points, is_good, image_id=image)
|
||||
task = Task(name=name, points=points, is_good=is_good, image_id=image)
|
||||
task_db.insert(task.to_dict())
|
||||
send_event_to_user("user123", Event(EventType.TASK_CREATED.value,
|
||||
TaskCreated(task.id, "created")))
|
||||
return jsonify({'message': f'Task {name} added.'}), 201
|
||||
|
||||
@task_api.route('/task/<id>', methods=['GET'])
|
||||
@@ -44,6 +53,9 @@ def delete_task(id):
|
||||
if id in tasks:
|
||||
tasks.remove(id)
|
||||
child_db.update({'tasks': tasks}, ChildQuery.id == child.get('id'))
|
||||
send_event_to_user("user123", Event(EventType.TASK_DELETED.value,
|
||||
TaskDeleted(id, "deleted")))
|
||||
|
||||
return jsonify({'message': f'Task {id} deleted.'}), 200
|
||||
return jsonify({'error': 'Task not found'}), 404
|
||||
|
||||
@@ -85,4 +97,6 @@ def edit_task(id):
|
||||
|
||||
task_db.update(updates, TaskQuery.id == id)
|
||||
updated = task_db.get(TaskQuery.id == id)
|
||||
send_event_to_user("user123", Event(EventType.TASK_EDITED.value,
|
||||
TaskEdited(id, "edited")))
|
||||
return jsonify(updated), 200
|
||||
|
||||
Reference in New Issue
Block a user