Created
May 15, 2026 14:22
-
-
Save feliperoberto/88ff2b286b385f2ab23b49460fcbefd0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| Questions: | |
| 1. Complete the `MiniVenmo.create_user()` method to allow our application to create new users. | |
| 2. Complete the `User.pay()` method to allow users to pay each other. Consider the following: if user A is paying user B, user's A balance should be used if there's enough balance to cover the whole payment, if not, user's A credit card should be charged instead. | |
| 3. Venmo has the Feed functionality, that shows the payments that users have been doing in the app. If Bobby paid Carol $5, and then Carol paid Bobby $15, it should look something like this | |
| Bobby paid Carol $5.00 for Coffee | |
| Carol paid Bobby $15.00 for Lunch | |
| Implement the `User.retrieve_feed()` and `MiniVenmo.render_feed()` methods so the MiniVenmo application can render the feed. | |
| 4. Now users should be able to add friends. Implement the `User.add_friend()` method to allow users to add friends. | |
| 5. Now modify the methods involved in rendering the feed to also show when user's added each other as friends. | |
| """ | |
| """ | |
| MiniVenmo! Imagine that your phone and wallet are trying to have a beautiful | |
| baby. In order to make this happen, you must write a social payment app. | |
| Implement a program that will feature users, credit cards, and payment feeds. | |
| """ | |
| import re | |
| import unittest | |
| import uuid | |
| class UsernameException(Exception): | |
| pass | |
| class PaymentException(Exception): | |
| pass | |
| class CreditCardException(Exception): | |
| pass | |
| class Payment: | |
| def __init__(self, amount, actor, target, note): | |
| self.id = str(uuid.uuid4()) | |
| self.amount = float(amount) | |
| self.actor = actor | |
| self.target = target | |
| self.note = note | |
| def __str__(self): | |
| return print(f" paid {self.target} ${self.amount} for {self.note}") | |
| class User: | |
| feed = [] | |
| friends = {} | |
| def __init__(self, username): | |
| self.credit_card_number = None | |
| self.balance = 0.0 | |
| if self._is_valid_username(username): | |
| self.username = username | |
| else: | |
| raise UsernameException('Username not valid.') | |
| def retrieve_feed(self): | |
| return self.feed | |
| def add_to_feed(self, payment): | |
| # Bobby paid Carol $5.00 for Coffee | |
| # Carol paid Bobby $15.00 for Lunch | |
| self.feed.append(payment) | |
| def add_friend(self, new_friend: "User"): | |
| self.friends[new_friend.username] = new_friend | |
| self.feed.append(new_friend) | |
| def add_to_balance(self, amount): | |
| self.balance += float(amount) | |
| def add_credit_card(self, credit_card_number): | |
| if self.credit_card_number is not None: | |
| raise CreditCardException('Only one credit card per user!') | |
| if self._is_valid_credit_card(credit_card_number): | |
| self.credit_card_number = credit_card_number | |
| else: | |
| raise CreditCardException('Invalid credit card number.') | |
| def pay(self, target, amount, note): | |
| # TODO: add logic to pay with card or balance | |
| if amount <= self.balance: | |
| payment = self.pay_with_balance(target, amount, note) | |
| else: | |
| payment = self.pay_with_card(target, amount, note) | |
| self.add_to_feed(payment) | |
| def _basic_validation(self, amount, target): | |
| if self.username == target.username: | |
| raise PaymentException('User cannot pay themselves.') | |
| elif amount <= 0.0: | |
| raise PaymentException('Amount must be a non-negative number.') | |
| def pay_with_card(self, target: "User", amount, note) -> Payment: | |
| amount = float(amount) | |
| self._basic_validation(amount, target) | |
| if self.credit_card_number is None: | |
| raise PaymentException('Must have a credit card to make a payment.') | |
| self._charge_credit_card(self.credit_card_number) | |
| payment = Payment(amount, self, target, note) | |
| target.add_to_balance(amount) | |
| return payment | |
| def pay_with_balance(self, target: "User", amount, note) -> Payment: | |
| # TODO: add code here | |
| amount = float(amount) | |
| self._basic_validation(amount, target) | |
| payment = Payment(amount, self, target, note) | |
| target.add_to_balance(amount) | |
| self.add_to_balance(amount * -1) | |
| return payment | |
| def _is_valid_credit_card(self, credit_card_number): | |
| return credit_card_number in ["4111111111111111", "4242424242424242"] | |
| def _is_valid_username(self, username): | |
| return re.match('^[A-Za-z0-9_\\-]{4,15}$', username) | |
| def _charge_credit_card(self, credit_card_number): | |
| # magic method that charges a credit card thru the card processor | |
| pass | |
| class MiniVenmo: | |
| def create_user(self, username, balance, credit_card_number) -> User: | |
| user = User(username) | |
| user.add_to_balance(balance) | |
| user.add_credit_card(credit_card_number) | |
| return user | |
| def render_feed(self, feed: list[Payment]): | |
| # Bobby paid Carol $5.00 for Coffee | |
| # Bobby added Carol as a friend | |
| for feed_entry in feed: | |
| if type(feed_entry) == type(Payment): | |
| print(feed_entry) | |
| if type(feed_entry) == type(User): | |
| print(f"Added {feed_entry.username} as a friend.") | |
| @classmethod | |
| def run(cls): | |
| venmo = cls() | |
| bobby = venmo.create_user("Bobby", 5.00, "4111111111111111") | |
| carol = venmo.create_user("Carol", 10.00, "4242424242424242") | |
| try: | |
| # should complete using balance | |
| bobby.pay(carol, 5.00, "Coffee") | |
| # should complete using card | |
| carol.pay(bobby, 15.00, "Lunch") | |
| except PaymentException as e: | |
| print(e) | |
| feed = bobby.retrieve_feed() | |
| venmo.render_feed(feed) | |
| bobby.add_friend(carol) | |
| class TestUser(unittest.TestCase): | |
| def test_this_works(self): | |
| with self.assertRaises(UsernameException): | |
| raise UsernameException() | |
| class TestMiniVenmo(unittest.TestCase): | |
| def test_create_user(self): | |
| venmo = MiniVenmo() | |
| bobby = venmo.create_user("Bobby", 5.00, "4111111111111111") | |
| assert bobby.username == "Bobby" | |
| assert bobby.balance == 5 | |
| assert bobby.credit_card_number == "4111111111111111" | |
| def test_pay_with_balance(self): | |
| venmo = MiniVenmo() | |
| bobby = venmo.create_user("Bobby", 5.00, "4111111111111111") | |
| carol = venmo.create_user("Carol", 10.00, "4242424242424242") | |
| # should complete using balance | |
| bobby.pay(carol, 5.00, "Coffee") | |
| # should complete using card | |
| carol.pay(bobby, 15.00, "Lunch") | |
| assert bobby.balance == 15 | |
| def test_pay_with_credit_card(self): | |
| venmo = MiniVenmo() | |
| bobby = venmo.create_user("Bobby", 5.00, "4111111111111111") | |
| carol = venmo.create_user("Carol", 10.00, "4242424242424242") | |
| # should complete using balance | |
| bobby.pay(carol, 5.00, "Coffee") | |
| # should complete using card | |
| carol.pay(bobby, 15.00, "Lunch") | |
| assert carol.balance == 0 | |
| if __name__ == '__main__': | |
| unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment