Finished
1import json
2
13class RestAPI:
24 def __init__(self, database: dict | None = None):
3 pass
4
5 """
6 Initialize the REST API with a database.
7
8 Args:
9 database: A dictionary containing user data.
10 """
11 # Edge Case: Handle None database by initializing empty structure
12 if database is None:
13 self.database = {"users": []}
14 else:
15 self.database = database
16
517 def get(self, url: str, payload: str | None = None) -> str:
6 pass
7
18 """
19 Handle GET requests to the API.
20
21 Args:
22 url: The endpoint being accessed.
23 payload: Optional JSON payload with request parameters.
24
25 Returns:
26 JSON string response.
27
28 Raises:
29 ValueError: If URL is not recognized.
30 """
31 # Edge Case: Handle /users endpoint
32 if url == "/users":
33 # Edge Case: Handle payload filtering
34 if payload is not None:
35 data = json.loads(payload)
36 if "users" in data:
37 # Filter users by provided list
38 filtered_users = [user for user in self.database["users"] if user["name"] in data["users"]]
39 # Sort by name
40 filtered_users.sort(key=lambda x: x["name"])
41 return json.dumps({"users": filtered_users})
42 # Return all users sorted by name
43 sorted_users = sorted(self.database["users"], key=lambda x: x["name"])
44 return json.dumps({"users": sorted_users})
45 # Edge Case: Handle unknown URLs
46 else:
47 raise ValueError(f"Unknown URL: {url}")
48 # Handled Edge Cases: /users endpoint, payload filtering, unknown URLs
49
850 def post(self, url: str, payload: str | None = None) -> str:
9 pass
51 """
52 Handle POST requests to the API.
53
54 Args:
55 url: The endpoint being accessed.
56 payload: JSON payload with request data.
57
58 Returns:
59 JSON string response.
60
61 Raises:
62 ValueError: If URL is not recognized or if data is invalid.
63 """
64 # Edge Case: Handle None payload
65 if payload is None:
66 raise ValueError("Payload is required")
67
68 data = json.loads(payload)
69
70 # Edge Case: Handle /add endpoint
71 if url == "/add":
72 # Edge Case: Check if user field exists
73 if "user" not in data:
74 raise ValueError("User field is required")
75
76 user_name = data["user"]
77
78 # Edge Case: Check if user already exists
79 for user in self.database["users"]:
80 if user["name"] == user_name:
81 raise ValueError(f"User {user_name} already exists")
82
83 # Create new user
84 new_user = {
85 "name": user_name,
86 "owes": {},
87 "owed_by": {},
88 "balance": 0.0
89 }
90
91 self.database["users"].append(new_user)
92 return json.dumps(new_user)
93
94 # Edge Case: Handle /iou endpoint
95 elif url == "/iou":
96 # Edge Case: Validate required fields
97 required_fields = ["lender", "borrower", "amount"]
98 for field in required_fields:
99 if field not in data:
100 raise ValueError(f"Missing required field: {field}")
101
102 lender_name = data["lender"]
103 borrower_name = data["borrower"]
104 amount = data["amount"]
105
106 # Edge Case: Validate amount is positive
107 if amount <= 0:
108 raise ValueError("Amount must be positive")
109
110 # Edge Case: Validate lender and borrower are different
111 if lender_name == borrower_name:
112 raise ValueError("Lender and borrower must be different")
113
114 # Find lender and borrower
115 lender = None
116 borrower = None
117
118 for user in self.database["users"]:
119 if user["name"] == lender_name:
120 lender = user
121 elif user["name"] == borrower_name:
122 borrower = user
123
124 # Edge Case: Validate both users exist
125 if lender is None:
126 raise ValueError(f"User {lender_name} does not exist")
127 if borrower is None:
128 raise ValueError(f"User {borrower_name} does not exist")
129
130 # Update IOUs
131 # If lender is owed by borrower, adjust that amount
132 if borrower_name in lender["owed_by"]:
133 lender["owed_by"][borrower_name] += amount
134 else:
135 lender["owed_by"][borrower_name] = amount
136
137 # If borrower owes lender, adjust that amount
138 if lender_name in borrower["owes"]:
139 borrower["owes"][lender_name] += amount
140 else:
141 borrower["owes"][lender_name] = amount
142
143 # If borrower is owed by lender, we need to net the amounts
144 if borrower_name in lender["owes"]:
145 # Edge Case: Handle netting of debts
146 lender_owes_borrower = lender["owes"][borrower_name]
147 lender_owed_by_borrower = lender["owed_by"][borrower_name]
148
149 if lender_owes_borrower > lender_owed_by_borrower:
150 # Net down the owes amount
151 lender["owes"][borrower_name] = lender_owes_borrower - lender_owed_by_borrower
152 # Remove the owed_by entry
153 del lender["owed_by"][borrower_name]
154 # Update borrower's records
155 del borrower["owes"][lender_name]
156 borrower["owed_by"][lender_name] = lender_owes_borrower - lender_owed_by_borrower
157 elif lender_owes_borrower < lender_owed_by_borrower:
158 # Net down the owed_by amount
159 lender["owed_by"][borrower_name] = lender_owed_by_borrower - lender_owes_borrower
160 # Remove the owes entry
161 del lender["owes"][borrower_name]
162 # Update borrower's records
163 del borrower["owed_by"][lender_name]
164 borrower["owes"][lender_name] = lender_owed_by_borrower - lender_owes_borrower
165 else: # Equal amounts
166 # Remove both entries
167 del lender["owes"][borrower_name]
168 del lender["owed_by"][borrower_name]
169 del borrower["owes"][lender_name]
170 del borrower["owed_by"][lender_name]
171
172 # Recalculate balances
173 lender_total_owed = sum(lender["owed_by"].values())
174 lender_total_owes = sum(lender["owes"].values())
175 lender["balance"] = lender_total_owed - lender_total_owes
176
177 borrower_total_owed = sum(borrower["owed_by"].values())
178 borrower_total_owes = sum(borrower["owes"].values())
179 borrower["balance"] = borrower_total_owed - borrower_total_owes
180
181 # Return updated users sorted by name
182 updated_users = [lender, borrower]
183 updated_users.sort(key=lambda x: x["name"])
184 return json.dumps({"users": updated_users})
185
186 # Edge Case: Handle unknown URLs
187 else:
188 raise ValueError(f"Unknown URL: {url}")
189 # Handled Edge Cases: None payload, /add endpoint, /iou endpoint, missing fields,
190 # negative amounts, same lender/borrower, non-existent users,
191 # netting of debts, unknown URLs
Test NameStatus
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_lender_owes_borrower
Pass
test_lender_owes_borrower_less_than_new_loan
Pass
test_lender_owes_borrower_same_as_new_loan
Pass
test_no_users
Pass

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