296 lines
10 KiB
Python
296 lines
10 KiB
Python
from flask import Blueprint, request, jsonify
|
|
from tinydb import Query
|
|
from db.db import child_db, task_db, reward_db
|
|
from api.reward_status import RewardStatus
|
|
from api.child_tasks import ChildTask
|
|
|
|
from models.child import Child
|
|
from models.task import Task
|
|
from models.reward import Reward
|
|
|
|
child_api = Blueprint('child_api', __name__)
|
|
|
|
@child_api.route('/child/<name>', methods=['GET'])
|
|
@child_api.route('/child/<id>', methods=['GET'])
|
|
def get_child(id):
|
|
ChildQuery = Query()
|
|
result = child_db.search(ChildQuery.id == id)
|
|
if not result:
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
return jsonify(result[0]), 200
|
|
|
|
@child_api.route('/child/add', methods=['PUT'])
|
|
def add_child():
|
|
data = request.get_json()
|
|
name = data.get('name')
|
|
age = data.get('age')
|
|
image = data.get('image_id', None)
|
|
if not name:
|
|
return jsonify({'error': 'Name is required'}), 400
|
|
if not image:
|
|
image = 'boy01'
|
|
|
|
child = Child(name, age, image_id=image)
|
|
child_db.insert(child.to_dict())
|
|
return jsonify({'message': f'Child {name} added.'}), 201
|
|
|
|
@child_api.route('/child/<id>/edit', methods=['PUT'])
|
|
def edit_child(id):
|
|
data = request.get_json()
|
|
name = data.get('name', None)
|
|
age = data.get('age', None)
|
|
points = data.get('points', None)
|
|
image = data.get('image_id', None)
|
|
ChildQuery = Query()
|
|
result = child_db.search(ChildQuery.id == id)
|
|
if not result:
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
child = result[0]
|
|
if name is not None:
|
|
child['name'] = name
|
|
if age is not None:
|
|
child['age'] = age
|
|
if points is not None:
|
|
child['points'] = points
|
|
if image is not None:
|
|
child['image_id'] = image
|
|
child_db.update(child, ChildQuery.id == id)
|
|
return jsonify({'message': f'Child {id} updated.'}), 200
|
|
|
|
@child_api.route('/child/list', methods=['GET'])
|
|
def list_children():
|
|
children = child_db.all()
|
|
return jsonify({'children': children}), 200
|
|
|
|
# Child DELETE
|
|
@child_api.route('/child/<id>', methods=['DELETE'])
|
|
def delete_child(id):
|
|
ChildQuery = Query()
|
|
if child_db.remove(ChildQuery.id == id):
|
|
return jsonify({'message': f'Child {id} deleted.'}), 200
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
|
|
@child_api.route('/child/<id>/assign-task', methods=['POST'])
|
|
def assign_task_to_child(id):
|
|
data = request.get_json()
|
|
task_id = data.get('task_id')
|
|
if not task_id:
|
|
return jsonify({'error': 'task_id is required'}), 400
|
|
|
|
ChildQuery = Query()
|
|
result = child_db.search(ChildQuery.id == id)
|
|
if not result:
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
|
|
child = result[0]
|
|
if task_id not in child.get('tasks', []):
|
|
child['tasks'].append(task_id)
|
|
child_db.update({'tasks': child['tasks']}, ChildQuery.id == id)
|
|
return jsonify({'message': f'Task {task_id} assigned to {child['name']}.'}), 200
|
|
|
|
|
|
|
|
@child_api.route('/child/<id>/remove-task', methods=['POST'])
|
|
def remove_task_from_child(id):
|
|
data = request.get_json()
|
|
task_id = data.get('task_id')
|
|
if not task_id:
|
|
return jsonify({'error': 'task_id is required'}), 400
|
|
|
|
ChildQuery = Query()
|
|
result = child_db.search(ChildQuery.id == id)
|
|
if not result:
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
|
|
child = result[0]
|
|
if task_id in child.get('tasks', []):
|
|
child['tasks'].remove(task_id)
|
|
child_db.update({'tasks': child['tasks']}, ChildQuery.id == id)
|
|
return jsonify({'message': f'Task {task_id} removed from {child["name"]}.'}), 200
|
|
return jsonify({'error': 'Task not assigned to child'}), 400
|
|
|
|
@child_api.route('/child/<id>/list-tasks', methods=['GET'])
|
|
def list_child_tasks(id):
|
|
ChildQuery = Query()
|
|
result = child_db.search(ChildQuery.id == id)
|
|
if not result:
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
|
|
child = result[0]
|
|
task_ids = child.get('tasks', [])
|
|
|
|
TaskQuery = Query()
|
|
child_tasks = []
|
|
for tid in task_ids:
|
|
task = task_db.get(TaskQuery.id == tid)
|
|
if not task:
|
|
continue
|
|
ct = ChildTask(task.get('name'), task.get('is_good'), task.get('points'), task.get('image_id'), task.get('id'))
|
|
child_tasks.append(ct.to_dict())
|
|
|
|
return jsonify({'child_tasks': child_tasks}), 200
|
|
|
|
@child_api.route('/child/<id>/list-assignable-tasks', methods=['GET'])
|
|
def list_assignable_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', []))
|
|
|
|
# Collect all task ids from the task database
|
|
all_task_ids = [t.get('id') for t in task_db.all() if t and t.get('id')]
|
|
|
|
# Filter out already assigned
|
|
assignable_ids = [tid for tid in all_task_ids if tid not in assigned_ids]
|
|
|
|
# Fetch full task details and wrap in ChildTask
|
|
TaskQuery = Query()
|
|
assignable_tasks = []
|
|
for tid in assignable_ids:
|
|
task = task_db.get(TaskQuery.id == tid)
|
|
if not task:
|
|
continue
|
|
ct = ChildTask(task.get('name'), task.get('is_good'), task.get('points'), task.get('image_id'), task.get('id'))
|
|
assignable_tasks.append(ct.to_dict())
|
|
|
|
return jsonify({'assignable_tasks': assignable_tasks, 'count': len(assignable_tasks)}), 200
|
|
|
|
@child_api.route('/child/<id>/trigger-task', methods=['POST'])
|
|
def trigger_child_task(id):
|
|
data = request.get_json()
|
|
task_id = data.get('task_id')
|
|
if not task_id:
|
|
return jsonify({'error': 'task_id is required'}), 400
|
|
|
|
ChildQuery = Query()
|
|
result = child_db.search(ChildQuery.id == id)
|
|
if not result:
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
|
|
child: Child = Child.from_dict(result[0])
|
|
if task_id not in child.tasks:
|
|
return jsonify({'error': f'Task not found assigned to child {child.name}'}), 404
|
|
# look up the task and get the details
|
|
TaskQuery = Query()
|
|
task_result = task_db.search(TaskQuery.id == task_id)
|
|
if not task_result:
|
|
return jsonify({'error': 'Task not found in task database'}), 404
|
|
task: Task = Task.from_dict(task_result[0])
|
|
# update the child's points based on task type
|
|
if task.is_good:
|
|
child.points += task.points
|
|
else:
|
|
child.points -= task.points
|
|
child.points = max(child.points, 0)
|
|
# update the child in the database
|
|
child_db.update({'points': child.points}, ChildQuery.id == id)
|
|
|
|
return jsonify({'message': f'{task.name} points assigned to {child.name}.', 'points': child.points, 'id': child.id}), 200
|
|
|
|
@child_api.route('/child/<id>/assign-reward', methods=['POST'])
|
|
def assign_reward_to_child(id):
|
|
data = request.get_json()
|
|
reward_id = data.get('reward_id')
|
|
if not reward_id:
|
|
return jsonify({'error': 'reward_id is required'}), 400
|
|
|
|
ChildQuery = Query()
|
|
result = child_db.search(ChildQuery.id == id)
|
|
if not result:
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
|
|
child = result[0]
|
|
if reward_id not in child.get('rewards', []):
|
|
child['rewards'].append(reward_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>/remove-reward', methods=['POST'])
|
|
def remove_reward_from_child(id):
|
|
data = request.get_json()
|
|
reward_id = data.get('reward_id')
|
|
if not reward_id:
|
|
return jsonify({'error': 'reward_id is required'}), 400
|
|
|
|
ChildQuery = Query()
|
|
result = child_db.search(ChildQuery.id == id)
|
|
if not result:
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
|
|
child = result[0]
|
|
if reward_id in child.get('rewards', []):
|
|
child['rewards'].remove(reward_id)
|
|
child_db.update({'rewards': child['rewards']}, ChildQuery.id == id)
|
|
return jsonify({'message': f'Reward {reward_id} removed from {child["name"]}.'}), 200
|
|
return jsonify({'error': 'Reward not assigned to child'}), 400
|
|
|
|
@child_api.route('/child/<id>/trigger-reward', methods=['POST'])
|
|
def trigger_child_reward(id):
|
|
data = request.get_json()
|
|
reward_id = data.get('reward_id')
|
|
if not reward_id:
|
|
return jsonify({'error': 'reward_id is required'}), 400
|
|
|
|
ChildQuery = Query()
|
|
result = child_db.search(ChildQuery.id == id)
|
|
if not result:
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
|
|
child: Child = Child.from_dict(result[0])
|
|
if reward_id not in child.rewards:
|
|
return jsonify({'error': f'Reward not found assigned to child {child.name}'}), 404
|
|
# look up the task and get the details
|
|
RewardQuery = Query()
|
|
reward_result = reward_db.search(RewardQuery.id == reward_id)
|
|
if not reward_result:
|
|
return jsonify({'error': 'Reward not found in reward database'}), 404
|
|
reward: Reward = Reward.from_dict(reward_result[0])
|
|
# update the child's points based on reward cost
|
|
child.points -= reward.cost
|
|
# update the child in the database
|
|
child_db.update({'points': child.points}, ChildQuery.id == id)
|
|
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'])
|
|
def list_affordable_rewards(id):
|
|
ChildQuery = Query()
|
|
result = child_db.search(ChildQuery.id == id)
|
|
if not result:
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
|
|
child = result[0]
|
|
points = child.get('points', 0)
|
|
reward_ids = child.get('rewards', [])
|
|
RewardQuery = Query()
|
|
affordable = [
|
|
reward for reward_id in reward_ids
|
|
if (reward := reward_db.get(RewardQuery.id == reward_id)) and points >= reward.get('cost', 0)
|
|
]
|
|
return jsonify({'affordable_rewards': affordable}), 200
|
|
|
|
@child_api.route('/child/<id>/reward-status', methods=['GET'])
|
|
def reward_status(id):
|
|
ChildQuery = Query()
|
|
result = child_db.search(ChildQuery.id == id)
|
|
if not result:
|
|
return jsonify({'error': 'Child not found'}), 404
|
|
|
|
child = result[0]
|
|
points = child.get('points', 0)
|
|
reward_ids = child.get('rewards', [])
|
|
|
|
RewardQuery = Query()
|
|
statuses = []
|
|
for reward_id in reward_ids:
|
|
reward = 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'))
|
|
statuses.append(status.to_dict())
|
|
|
|
statuses.sort(key=lambda s: s['points_needed'])
|
|
return jsonify({'reward_status': statuses}), 200 |