Пример #1
0
    def test_bid_higher_than_maximum_price_fails(self):
        strategy = HighestContributionBiddingStrategy(
            minimum_bid_amount=Decimal(5), maximum_price=Decimal(100))
        strategy.auction = Mock()
        strategy.start()

        bidder_1 = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="the kid is micheal's son",
            first_name="Billie",
            last_name="Jean",
        )
        bidder_2 = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="the kid is not my son",
            first_name="Billie",
            last_name="Jean",
        )

        bidder_1.persistent_user = Mock(id=1)
        bidder_2.persistent_user = Mock(id=2)
        bidder_1.initial_balance = 60
        bidder_2.initial_balance = 60

        strategy.bid(bidder=bidder_1, amount=Decimal(40))
        strategy.bid(bidder=bidder_2, amount=Decimal(40))
        with self.assertRaises(InsufficientBalanceError):
            strategy.bid(bidder=bidder_2, amount=Decimal(40))
Пример #2
0
    def test_bid_bidder_has_insufficient_balance(self):
        strategy = IncrementBiddingStrategy(initial_price=Decimal(3.00))
        strategy.auction = Mock()
        strategy.start()
        bidder_1 = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="the kid is micheal's son",
            first_name="Billie",
            last_name="Jean",
        )

        bidder_1.initial_balance = 10

        with self.assertRaises(InsufficientBalanceError):
            strategy.bid(bidder=bidder_1, amount=Decimal(20))

        strategy.stop()
Пример #3
0
    def get_or_create_runtime_user(self, user: User):
        from bidpazari.core.runtime.user import RuntimeUser

        runtime_user = self.get_user_by_id(user.id)

        if runtime_user is None:
            runtime_user = RuntimeUser.from_persistent_user(user)
            runtime_user.connect()

        return runtime_user
Пример #4
0
async def login(context: CommandContext, username: str, password: str):
    if context.runtime_user:
        raise CommandFailed("You are already logged in!")

    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        raise CommandFailed("Incorrect username or password.")

    if user.check_password(password):
        runtime_user = RuntimeUser.from_persistent_user(user)
    else:
        raise CommandFailed("Incorrect username or password.")

    runtime_user.connect()
    context.runtime_user = runtime_user
    return {"user": {"id": runtime_user.id}}
Пример #5
0
    def test_get_current_winner_and_amount(self):
        strategy = HighestContributionBiddingStrategy(
            minimum_bid_amount=Decimal(5), maximum_price=Decimal(150))
        strategy.auction = Mock()
        strategy.start()

        bidder_1 = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="the kid is micheal's son",
            first_name="Billie",
            last_name="Jean",
        )
        bidder_2 = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="the kid is not my son",
            first_name="Billie",
            last_name="Jean",
        )

        bidder_1.persistent_user = Mock(id=1)
        bidder_2.persistent_user = Mock(id=2)
        bidder_1.initial_balance = 60
        bidder_2.initial_balance = 60

        self.assertEqual(strategy.get_current_winner_and_amount(),
                         (None, None))
        self.assertEqual(strategy.get_current_price(), Decimal(0))

        strategy.bid(bidder=bidder_1, amount=Decimal(40))
        self.assertEqual(strategy.get_current_winner_and_amount(),
                         (bidder_1, Decimal(40)))

        strategy.bid(bidder=bidder_1, amount=Decimal(20))
        self.assertEqual(strategy.get_current_winner_and_amount(),
                         (bidder_1, Decimal(60)))

        strategy.bid(bidder=bidder_2, amount=Decimal(50))
        self.assertEqual(strategy.get_current_winner_and_amount(),
                         (bidder_1, Decimal(60)))
Пример #6
0
async def create_user(
    context: CommandContext,
    username: str,
    password: str,
    email: str,
    first_name: str,
    last_name: str,
):
    """
    Creates an user and immediately logs in.
    """
    user = User.objects.create_user(
        username=username,
        password=password,
        email=email,
        first_name=first_name,
        last_name=last_name,
    )
    runtime_user = RuntimeUser.from_persistent_user(user)
    context.runtime_user = runtime_user
    return {'user': {'id': user.id}}
Пример #7
0
    def test_get_current_winner_and_amount(self):
        strategy = IncrementBiddingStrategy(initial_price=Decimal(3.00))
        strategy.auction = Mock()
        strategy.start()
        self.assertEqual((None, None),
                         strategy.get_current_winner_and_amount())

        bidder_1 = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="the kid is micheal's son",
            first_name="Billie",
            last_name="Jean",
        )
        bidder_2 = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="the kid is not my son",
            first_name="Billie",
            last_name="Jean",
        )

        bidder_1.persistent_user = Mock(id=1)
        bidder_2.persistent_user = Mock(id=2)
        bidder_1.initial_balance = 10
        bidder_2.initial_balance = 20

        self.assertEqual(Decimal(3), strategy.get_current_price())

        strategy.bid(bidder=bidder_1, amount=Decimal(4))
        strategy.bid(bidder=bidder_2, amount=Decimal(5))
        self.assertEqual(Decimal(5), strategy.get_current_price())

        strategy.bid(bidder=bidder_1, amount=Decimal(6))
        strategy.stop()

        self.assertEqual((bidder_1, Decimal(6)),
                         strategy.get_current_winner_and_amount())
Пример #8
0
    def test_highest_contribution_bidding_maximum_price(self):
        john = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="11441144",
            first_name="John",
            last_name="Sims",
        )
        jimmy = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="12345678",
            first_name="James",
            last_name="Hetfield",
        )
        jack = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="i_secretly_like_johnny_walker",
            first_name="Jack",
            last_name="Daniels",
        )

        john.persist()
        jimmy.persist()
        jack.persist()

        john.connect()
        jimmy.connect()
        jack.connect()

        john.add_balance_transaction(Decimal(150.00))
        jimmy.add_balance_transaction(Decimal(140.00))
        jack.add_balance_transaction(Decimal(130.00))

        scarf = Item.objects.create(title="Scarf",
                                    description="A really cool scarf",
                                    item_type="Clothing")
        jimmy_has_scarf = UserHasItem.objects.create(
            item=scarf, user=jimmy.persistent_user)

        auction = runtime_manager.create_auction(
            uhi=jimmy_has_scarf,
            bidding_strategy_identifier="highest_contribution",
            minimum_bid_amount=Decimal(2.00),
            maximum_price=Decimal(100),
        )

        auction.start()

        auction.bid(jack, Decimal(30.00))
        auction.bid(john, Decimal(50.00))
        auction.bid(jack, Decimal(30.00))

        print(auction.auction_report)
        print(auction.auction_history)

        john.persistent_user.refresh_from_db()
        jimmy.persistent_user.refresh_from_db()
        jack.persistent_user.refresh_from_db()
        jimmy_has_scarf.refresh_from_db()

        john.disconnect()
        jimmy.disconnect()
        jack.disconnect()

        self.assertTrue(jimmy_has_scarf.is_sold)
        self.assertEqual(john.initial_balance, Decimal(100))
        self.assertEqual(jimmy.initial_balance, Decimal(250))
        self.assertEqual(jack.initial_balance, Decimal(70))
        self.assertEqual(john.persistent_user.balance, Decimal(100))
        self.assertEqual(jimmy.persistent_user.balance, Decimal(250))
        self.assertEqual(jack.persistent_user.balance, Decimal(70))
Пример #9
0
    def test_decrement_bidding_with_no_winners(self):
        pass
        john = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="11441144",
            first_name="John",
            last_name="Sims",
        )
        jimmy = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="12345678",
            first_name="James",
            last_name="Hetfield",
        )

        john.persist()
        jimmy.persist()

        john.connect()
        jimmy.connect()

        john.add_balance_transaction(Decimal(100.00))
        jimmy.add_balance_transaction(Decimal(40.00))

        scarf = Item.objects.create(title="Scarf",
                                    description="A really cool scarf",
                                    item_type="Clothing")
        jimmy_has_scarf = UserHasItem.objects.create(
            item=scarf, user=jimmy.persistent_user)

        auction = runtime_manager.create_auction(
            uhi=jimmy_has_scarf,
            bidding_strategy_identifier="decrement",
            initial_price=Decimal(150.00),
            price_decrement_rate=Decimal(50.00),
            tick_ms=20,
        )

        auction.start()

        self.assertEqual(auction.bidding_strategy.get_current_price(),
                         Decimal(150.00))
        sleep(25 / 1000)
        self.assertEqual(auction.bidding_strategy.get_current_price(),
                         Decimal(100.00))
        sleep(25 / 1000)
        self.assertEqual(auction.bidding_strategy.get_current_price(),
                         Decimal(50.00))
        sleep(25 / 1000)
        self.assertEqual(auction.bidding_strategy.get_current_price(),
                         Decimal(0.00))
        sleep(250 / 1000)

        print(auction.auction_report)
        print(auction.auction_history)

        john.persistent_user.refresh_from_db()
        jimmy.persistent_user.refresh_from_db()
        jimmy_has_scarf.refresh_from_db()

        john.disconnect()
        jimmy.disconnect()

        self.assertFalse(jimmy_has_scarf.is_sold)
        self.assertEqual(john.initial_balance, Decimal(100))
        self.assertEqual(jimmy.initial_balance, Decimal(40))
        self.assertEqual(john.persistent_user.balance, Decimal(100))
        self.assertEqual(jimmy.persistent_user.balance, Decimal(40))
Пример #10
0
    def test_decrement_bidding_and_auction_watching(self):
        john = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="11441144",
            first_name="John",
            last_name="Sims",
        )
        jimmy = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="12345678",
            first_name="James",
            last_name="Hetfield",
        )

        jimmy.watch_method = lambda *args, **kwargs: None
        patcher = patch.object(jimmy, "watch_method")
        m_jimmy_watch_method = patcher.start()

        john.persist()
        jimmy.persist()

        john.connect()
        jimmy.connect()

        john.add_balance_transaction(Decimal(100.00))
        jimmy.add_balance_transaction(Decimal(40.00))

        scarf = Item.objects.create(title="Scarf",
                                    description="A really cool scarf",
                                    item_type="Clothing")
        jimmy_has_scarf = UserHasItem.objects.create(
            item=scarf, user=jimmy.persistent_user)

        auction = runtime_manager.create_auction(
            uhi=jimmy_has_scarf,
            bidding_strategy_identifier="decrement",
            initial_price=Decimal(150.00),
            price_decrement_rate=Decimal(25.00),
            tick_ms=200,
        )

        auction.register_user_to_updates(jimmy.watch_method)  # this is mocked

        auction.start()

        self.assertEqual(auction.bidding_strategy.get_current_price(),
                         Decimal(150.00))
        with self.assertRaises(InsufficientBalanceError):
            auction.bid(
                john
            )  # no amount means that user is bidding to the current price
        sleep(250 / 1000)
        self.assertEqual(auction.bidding_strategy.get_current_price(),
                         Decimal(125.00))
        sleep(250 / 1000)
        self.assertEqual(auction.bidding_strategy.get_current_price(),
                         Decimal(100.00))
        auction.bid(john)  # this terminates the auction

        m_jimmy_watch_method.assert_has_calls([
            call(event_type="auction_started"),
            call(event_type="price_decremented", new_price=Decimal(125.00)),
            call(event_type="price_decremented", new_price=Decimal(100.00)),
            call(event_type="bid_received"),
            # TODO Fix this some day
            call(event_type="price_decremented", new_price=Decimal(75.00)),
            call(event_type="auction_stopped"),
        ])

        print(auction.auction_report)
        print(auction.auction_history)

        john.persistent_user.refresh_from_db()
        jimmy.persistent_user.refresh_from_db()
        jimmy_has_scarf.refresh_from_db()

        john.disconnect()
        jimmy.disconnect()

        self.assertTrue(jimmy_has_scarf.is_sold)
        self.assertEqual(john.initial_balance, Decimal(0))
        self.assertEqual(jimmy.initial_balance, Decimal(140))
        self.assertEqual(john.persistent_user.balance, Decimal(0))
        self.assertEqual(jimmy.persistent_user.balance, Decimal(140))

        patcher.stop()
Пример #11
0
    def test_increment_bidding_exceptions(self):
        john = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="11441144",
            first_name="John",
            last_name="Sims",
        )
        jimmy = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="12345678",
            first_name="James",
            last_name="Hetfield",
        )
        jack = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="i_secretly_like_johnny_walker",
            first_name="Jack",
            last_name="Daniels",
        )

        john.persist()
        jimmy.persist()
        jack.persist()

        john.connect()
        jimmy.connect()
        jack.connect()

        john.add_balance_transaction(Decimal(50.00))
        jimmy.add_balance_transaction(Decimal(40.00))
        jack.add_balance_transaction(Decimal(30.00))

        scarf = Item.objects.create(title="Scarf",
                                    description="A really cool scarf",
                                    item_type="Clothing")
        jimmy_has_scarf = UserHasItem.objects.create(
            item=scarf, user=jimmy.persistent_user)

        auction = runtime_manager.create_auction(
            uhi=jimmy_has_scarf,
            bidding_strategy_identifier="increment",
            initial_price=Decimal(5.00),
            minimum_increment=Decimal(2.00),
            maximum_price=Decimal(15.00),
        )

        # Cannot bid while auction is closed
        with self.assertRaises(BiddingNotAllowed) as cm:
            auction.bid(john, Decimal(123.00))
        self.assertEqual(cm.exception.reason, BiddingErrorReason.AuctionClosed)

        auction.start()

        # Cannot bid in own auction
        with self.assertRaises(BiddingNotAllowed) as cm:
            auction.bid(jimmy, Decimal(1.00))
        self.assertEqual(cm.exception.reason, BiddingErrorReason.OwnAuction)

        # Lower than initial price
        with self.assertRaises(BiddingNotAllowed) as cm:
            auction.bid(john, Decimal(1.00))
        self.assertEqual(cm.exception.reason,
                         BiddingErrorReason.InsufficientAmount)

        # Lower than minimum increment
        with self.assertRaises(BiddingNotAllowed) as cm:
            auction.bid(john, Decimal(6.00))
        self.assertEqual(cm.exception.reason,
                         BiddingErrorReason.InsufficientAmount)

        # Higher than reservable balance
        with self.assertRaises(InsufficientBalanceError):
            auction.bid(john, Decimal(666.00))

        # Happy path
        auction.bid(john, Decimal(7.00))
        self.assertEqual(john.reservable_balance, Decimal(43.00))
        auction.bid(john, Decimal(50.00))  # This closes the auction.
        self.assertEqual(john.reservable_balance, Decimal(0.00))

        print(auction.auction_report)
        print(auction.auction_history)

        # Cannot bid while auction is closed
        with self.assertRaises(BiddingNotAllowed) as cm:
            auction.bid(john, Decimal(123.00))
        self.assertEqual(cm.exception.reason, BiddingErrorReason.AuctionClosed)

        john.persistent_user.refresh_from_db()
        jimmy.persistent_user.refresh_from_db()
        jack.persistent_user.refresh_from_db()
        jimmy_has_scarf.refresh_from_db()

        john.disconnect()
        jimmy.disconnect()
        jack.disconnect()

        self.assertTrue(jimmy_has_scarf.is_sold)
        self.assertEqual(john.initial_balance, Decimal(0))
        self.assertEqual(jimmy.initial_balance, Decimal(90))
        self.assertEqual(jack.initial_balance, Decimal(30))
        self.assertEqual(john.persistent_user.balance, Decimal(0))
        self.assertEqual(jimmy.persistent_user.balance, Decimal(90))
        self.assertEqual(jack.persistent_user.balance, Decimal(30))
Пример #12
0
    def test_all(self):
        user = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="the kid is micheal's son",
            first_name="Billie",
            last_name="Jean",
        )
        user.persist()

        # Test verification number and verification flows
        actual_verification_number = user.persistent_user.verification_number
        self.assertEqual(user.persistent_user.verification_status,
                         User.UNVERIFIED)
        with self.assertRaises(UserVerificationError):
            user.verify("this is obviously not the correct validation number")
        self.assertEqual(user.persistent_user.verification_status,
                         User.UNVERIFIED)
        user.verify(actual_verification_number)
        self.assertEqual(user.persistent_user.verification_status,
                         User.VERIFIED)

        # Test password change flows
        with self.assertRaises(InvalidPassword):
            user.change_password(
                new_password="******",
                old_password="******",
            )
        newly_generated_password = user.change_password(new_password=None,
                                                        old_password=None)
        self.assertEqual(len(newly_generated_password), 16)
        user.change_password(new_password="******",
                             old_password=newly_generated_password)

        # Test item listing scenarios
        pencil = Item.objects.create(title="Pencil", item_type="Stationary")
        notepad = Item.objects.create(title="Notepad", item_type="Stationary")
        coffee_mug = Item.objects.create(title="Coffee Mug",
                                         item_type="Kitchen")
        towel = Item.objects.create(title="Towel",
                                    item_type="Kitchen",
                                    on_sale=True)
        watch = Item.objects.create(title="Watch",
                                    item_type="Accessory",
                                    on_sale=True)
        items = [pencil, notepad, coffee_mug, towel, watch]

        for item in items:
            UserHasItem.objects.create(user=user.persistent_user,
                                       item=item,
                                       is_sold=False)

        self.assertSetEqual(user.list_items(),
                            {pencil, notepad, coffee_mug, towel, watch})
        self.assertSetEqual(user.list_items(on_sale=True), {towel, watch})
        self.assertSetEqual(user.list_items(on_sale=False),
                            {pencil, notepad, coffee_mug})
        self.assertSetEqual(user.list_items(item_type="Kitchen"),
                            {coffee_mug, towel})
        self.assertSetEqual(user.list_items(item_type="Kitchen", on_sale=True),
                            {towel})

        # Test balance
        user.add_balance_transaction(Decimal(30.00))
        self.assertEqual(user.initial_balance, Decimal(30.00))
        user.add_balance_transaction(Decimal(-5.00))
        self.assertEqual(user.initial_balance, Decimal(25.00))

        # Test transaction history
        john = RuntimeUser(
            username="******",
            email="*****@*****.**",
            password_raw="11441144",
            first_name="John",
            last_name="Sims",
        )
        john.persist()

        # towel and watch are already on sale at this point

        Transaction.objects.create(
            source=user.persistent_user,
            destination=john.persistent_user,
            amount=Decimal(140.00),
            item=notepad,
        )
        Transaction.objects.create(
            source=john.persistent_user,
            destination=user.persistent_user,
            amount=Decimal(230.00),
            item=coffee_mug,
        )

        print(user.transaction_history)

        # Test item watching capabilities
        watcher_method = lambda item_on_auction, starting_price: None
        user.watcher_method = watcher_method

        patcher = patch.object(user, "watcher_method")
        m_user_watcher_method = patcher.start()

        user.register_item_watcher(user.watcher_method, item_type=None)
        auction = Mock(item=Mock(item_type="Furniture"),
                       initial_price=Decimal(10.99))
        runtime_manager.notify_users_of_new_auction(auction)
        m_user_watcher_method.assert_called_once()

        runtime_manager.item_watchers.clear()
        m_user_watcher_method.reset_mock()
        user.register_item_watcher(user.watcher_method, item_type="Vanity")
        auction = Mock(item=Mock(item_type="Vanity"),
                       initial_price=Decimal(10.99))
        runtime_manager.notify_users_of_new_auction(auction)
        m_user_watcher_method.assert_called_once()

        runtime_manager.item_watchers.clear()
        m_user_watcher_method.reset_mock()
        user.register_item_watcher(user.watcher_method, item_type="Kitchen")
        auction = Mock(item=Mock(item_type="Furniture"),
                       initial_price=Decimal(10.99))
        runtime_manager.notify_users_of_new_auction(auction)
        m_user_watcher_method.assert_not_called()

        patcher.stop()