let it go

Finished
1import json
2from typing import Dict, List, Optional, Any
3
14class RestAPI:
25 def __init__(self, database: dict | None = None):
3 pass
4
6 """
7 Initialize the REST API with a database of users.
8
9 Args:
10 database: A dictionary containing user data with the structure:
11 {"users": [{"name": str, "owes": dict, "owed_by": dict, "balance": float}]}
12 """
13 if database is None:
14 self.database = {"users": []}
15 else:
16 self.database = database
17
518 def get(self, url: str, payload: str | None = None) -> str:
6 pass
7
19 """
20 Handle GET requests to the API.
21
22 Args:
23 url: The endpoint URL (e.g., "/users")
24 payload: Optional JSON payload containing request parameters
25
26 Returns:
27 JSON string response
28 """
29 if url == "/users":
30 if payload is None:
31 # Return all users sorted by name
32 users = sorted(self.database["users"], key=lambda x: x["name"])
33 return json.dumps({"users": users})
34 else:
35 # Return only specified users sorted by name
36 payload_data = json.loads(payload)
37 user_names = payload_data.get("users", [])
38
39 # Edge Case: Empty users list in payload
40 if not user_names:
41 return json.dumps({"users": []})
42
43 # Filter users by name
44 filtered_users = [user for user in self.database["users"] if user["name"] in user_names]
45 # Sort by name
46 filtered_users.sort(key=lambda x: x["name"])
47 return json.dumps({"users": filtered_users})
48
49 # Edge Case: Invalid URL
50 return json.dumps({"error": "Invalid URL"})
51
852 def post(self, url: str, payload: str | None = None) -> str:
9 pass
53 """
54 Handle POST requests to the API.
55
56 Args:
57 url: The endpoint URL (e.g., "/add", "/iou")
58 payload: JSON payload containing request data
59
60 Returns:
61 JSON string response
62 """
63 if payload is None:
64 # Edge Case: Missing payload
65 return json.dumps({"error": "Payload required"})
66
67 try:
68 payload_data = json.loads(payload)
69 except json.JSONDecodeError:
70 # Edge Case: Invalid JSON payload
71 return json.dumps({"error": "Invalid JSON payload"})
72
73 if url == "/add":
74 user_name = payload_data.get("user")
75
76 # Edge Case: Missing user name
77 if not user_name:
78 return json.dumps({"error": "User name required"})
79
80 # Edge Case: User already exists
81 if any(user["name"] == user_name for user in self.database["users"]):
82 return json.dumps({"error": "User already exists"})
83
84 # Create new user
85 new_user = {
86 "name": user_name,
87 "owes": {},
88 "owed_by": {},
89 "balance": 0.0
90 }
91 self.database["users"].append(new_user)
92 return json.dumps(new_user)
93
94 elif url == "/iou":
95 lender_name = payload_data.get("lender")
96 borrower_name = payload_data.get("borrower")
97 amount = payload_data.get("amount")
98
99 # Edge Case: Missing required fields
100 if not lender_name or not borrower_name or amount is None:
101 return json.dumps({"error": "Lender, borrower, and amount are required"})
102
103 # Edge Case: Invalid amount type
104 if not isinstance(amount, (int, float)):
105 return json.dumps({"error": "Amount must be a number"})
106
107 # Edge Case: Negative amount
108 if amount < 0:
109 return json.dumps({"error": "Amount must be positive"})
110
111 # Edge Case: Lender and borrower are the same
112 if lender_name == borrower_name:
113 return json.dumps({"error": "Lender and borrower cannot be the same"})
114
115 # Find lender and borrower
116 lender = next((user for user in self.database["users"] if user["name"] == lender_name), None)
117 borrower = next((user for user in self.database["users"] if user["name"] == borrower_name), None)
118
119 # Edge Case: Lender or borrower does not exist
120 if not lender or not borrower:
121 return json.dumps({"error": "Lender or borrower does not exist"})
122
123 # Handle debt offsetting - check if borrower owes lender
124 # This happens when there's an existing debt in the opposite direction
125 if lender_name in borrower["owes"]:
126 # Borrower owes lender, so we need to offset
127 existing_debt = borrower["owes"][lender_name]
128 if existing_debt == amount:
129 # Debts cancel out completely
130 del borrower["owes"][lender_name]
131 if borrower_name in lender["owed_by"]:
132 del lender["owed_by"][borrower_name]
133 elif existing_debt > amount:
134 # Borrower still owes lender, reduce the debt
135 borrower["owes"][lender_name] = existing_debt - amount
136 if borrower_name in lender["owed_by"]:
137 del lender["owed_by"][borrower_name]
138 else:
139 # New loan is larger, reverse the debt direction
140 del borrower["owes"][lender_name]
141 if borrower_name in lender["owed_by"]:
142 del lender["owed_by"][borrower_name]
143 # Now lender owes borrower the difference
144 lender["owes"][borrower_name] = amount - existing_debt
145 borrower["owed_by"][lender_name] = amount - existing_debt
146 else:
147 # No existing debt in opposite direction, just add the new debt
148 # Update lender's owed_by (borrower owes lender)
149 if borrower_name in lender["owed_by"]:
150 lender["owed_by"][borrower_name] += amount
151 else:
152 lender["owed_by"][borrower_name] = amount
153
154 # Update borrower's owes (borrower owes lender)
155 if lender_name in borrower["owes"]:
156 borrower["owes"][lender_name] += amount
157 else:
158 borrower["owes"][lender_name] = amount
159
160 # Recalculate balances
161 lender_total_owed = sum(lender["owed_by"].values())
162 lender_total_owes = sum(lender["owes"].values())
163 lender["balance"] = lender_total_owed - lender_total_owes
164
165 borrower_total_owed = sum(borrower["owed_by"].values())
166 borrower_total_owes = sum(borrower["owes"].values())
167 borrower["balance"] = borrower_total_owed - borrower_total_owes
168
169 # Return updated users sorted by name
170 updated_users = sorted([lender, borrower], key=lambda x: x["name"])
171 return json.dumps({"users": updated_users})
172
173 # Edge Case: Invalid URL
174 return json.dumps({"error": "Invalid URL"})
175
176 # Handled Edge Cases: Invalid URL, Missing payload, Invalid JSON payload, Missing user name,
177 # User already exists, Missing required fields, Invalid amount type, Negative amount,
178 # Lender and borrower are the same, Lender or borrower does not exist, Empty users list in payload
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.