Finished
1import json
2from typing import Dict, List, Any
3
14class RestAPI:
25 def __init__(self, database: dict | None = None):
3 pass
6 if database is None:
7 self.database = {"users": []}
8 else:
9 self.database = database
410
511 def get(self, url: str, payload: str | None = None) -> str:
6 pass
12 if url == "/users":
13 if payload is None:
14 # Return all users sorted by name
15 users = sorted(self.database["users"], key=lambda x: x["name"])
16 return json.dumps({"users": users})
17 else:
18 try:
19 data = json.loads(payload)
20 if "users" not in data:
21 return json.dumps({"error": "Invalid payload"})
22
23 # Edge Case: Empty user list in GET request
24 if not data["users"]:
25 return json.dumps({"users": []})
26
27 # Filter users by the provided list
28 filtered_users = [user for user in self.database["users"] if user["name"] in data["users"]]
29 # Sort by name
30 filtered_users.sort(key=lambda x: x["name"])
31 return json.dumps({"users": filtered_users})
32 except json.JSONDecodeError:
33 return json.dumps({"error": "Invalid JSON payload"})
34 else:
35 return json.dumps({"error": "Invalid URL"})
736
837 def post(self, url: str, payload: str | None = None) -> str:
9 pass
38 if payload is None:
39 return json.dumps({"error": "Payload required"})
40
41 try:
42 data = json.loads(payload)
43 except json.JSONDecodeError:
44 return json.dumps({"error": "Invalid JSON payload"})
45
46 if url == "/add":
47 # Edge Case: Missing required fields in POST requests
48 if "user" not in data:
49 return json.dumps({"error": "Missing user field"})
50
51 user_name = data["user"]
52
53 # Edge Case: Invalid user names in requests
54 if not isinstance(user_name, str) or not user_name:
55 return json.dumps({"error": "Invalid user name"})
56
57 # Edge Case: Duplicate user creation
58 for user in self.database["users"]:
59 if user["name"] == user_name:
60 return json.dumps({"error": "User already exists"})
61
62 new_user = {
63 "name": user_name,
64 "owes": {},
65 "owed_by": {},
66 "balance": 0.0
67 }
68 self.database["users"].append(new_user)
69 return json.dumps(new_user)
70
71 elif url == "/iou":
72 # Edge Case: Missing required fields in POST requests
73 required_fields = ["lender", "borrower", "amount"]
74 for field in required_fields:
75 if field not in data:
76 return json.dumps({"error": f"Missing {field} field"})
77
78 lender_name = data["lender"]
79 borrower_name = data["borrower"]
80 amount = data["amount"]
81
82 # Edge Case: Invalid user names in requests
83 if not isinstance(lender_name, str) or not lender_name or not isinstance(borrower_name, str) or not borrower_name:
84 return json.dumps({"error": "Invalid user names"})
85
86 # Edge Case: Negative or zero amount values
87 if not isinstance(amount, (int, float)) or amount <= 0:
88 return json.dumps({"error": "Invalid amount"})
89
90 # Edge Case: Self-borrowing (user lending to themselves)
91 if lender_name == borrower_name:
92 return json.dumps({"error": "Cannot create IOU between same user"})
93
94 lender = None
95 borrower = None
96
97 # Find lender and borrower
98 for user in self.database["users"]:
99 if user["name"] == lender_name:
100 lender = user
101 if user["name"] == borrower_name:
102 borrower = user
103
104 # Edge Case: Non-existent users in IOU requests
105 if lender is None or borrower is None:
106 return json.dumps({"error": "User not found"})
107
108 # Update lender's owed_by and borrower's owes
109 # If borrower already owes lender, reduce that amount first
110 if borrower_name in lender["owed_by"]:
111 lender["owed_by"][borrower_name] += amount
112 else:
113 lender["owed_by"][borrower_name] = amount
114
115 if lender_name in borrower["owes"]:
116 borrower["owes"][lender_name] += amount
117 else:
118 borrower["owes"][lender_name] = amount
119
120 # Recalculate balances
121 lender_total_owed = sum(lender["owed_by"].values())
122 lender_total_owes = sum(lender["owes"].values())
123 lender["balance"] = lender_total_owed - lender_total_owes
124
125 borrower_total_owed = sum(borrower["owed_by"].values())
126 borrower_total_owes = sum(borrower["owes"].values())
127 borrower["balance"] = borrower_total_owed - borrower_total_owes
128
129 # Return updated users sorted by name
130 updated_users = [lender, borrower]
131 updated_users.sort(key=lambda x: x["name"])
132 return json.dumps({"users": updated_users})
133 else:
134 return json.dumps({"error": "Invalid URL"})
135
136 def _get_user(self, name: str) -> Dict | None:
137 for user in self.database["users"]:
138 if user["name"] == name:
139 return user
140 return None
141
142 def _calculate_balance(self, user: Dict) -> float:
143 total_owed_by = sum(user["owed_by"].values())
144 total_owes = sum(user["owes"].values())
145 return total_owed_by - total_owes
146
147# Handled Edge Cases: Duplicate user creation, Invalid user names in requests, Negative or zero amount values, Self-borrowing (user lending to themselves), Non-existent users in IOU requests, Missing required fields in POST requests, Invalid JSON payload format, Empty user list in GET request
Test NameStatus
test_lender_owes_borrower
Fail
test_lender_owes_borrower_less_than_new_loan
Fail
test_lender_owes_borrower_same_as_new_loan
Fail
test_add_user
Pass
test_borrower_has_negative_balance
Pass
test_both_users_have_0_balance
Pass
test_get_single_user
Pass
test_lender_has_negative_balance
Pass
test_no_users
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.