Example #1
0
def user_cart_checkout(_id):
    users = mongo.db.users
    items = mongo.db.items
    user = users.find_and_modify(
        {'_id': _id, 'trading': False},
        {'$set': {'cart': []}},
        fields={'cart': 1, 'items': 1},
    )
    if not user or not user.get('cart'):
        return False, 'no cart or user is trading'

    cart = user.get('cart', {})
    item_count = len(user.get('items', {}))
    if item_count > ITEM_LIMIT:
        return

    previous_gold = mongo.db.users.find_one(
        {'_id': _id}, {'credits': 1}
    ).get('credits', 0)
    # add items back to cart if we don't end up checking out
    errors = []
    added = []
    for item in cart:
        item_count += 1
        if item_count > ITEM_LIMIT:
            return

        query = {
            'class_id': item['class_id'],
            'instance_id': item['instance_id'],
        }
        item = lookup_single(query)
        if item:
            price = item.get('price')
            if not price:
                errors.append((item, 'no price set'))
                continue

            short_keys = {
                'app_id', 'context_id',
                'class_id', 'instance_id',
            }
            short_item = {}
            for key in short_keys:
                short_item[key] = item[key]

            # subtract money from user
            old = users.find_and_modify(
                {'_id': _id, 'credits': {'$gte': price}},
                {'$inc': {'credits': -price}},
                fields={'inventory': 0},
            )
            if not old:
                # couldn't afford it
                errors.append((item, 'not enough gold'))
                continue

            # modify stock available
            query = short_item.copy()
            query.update({'available': {'$gt': 0}})
            old = items.find_and_modify(query, {'$inc': {'available': -1}})
            if not old:
                # not enough of item available, refund money
                users.update({'_id': _id}, {'$inc': {'credits': price}})
                errors.append((item, 'out of stock'))
                continue

            # TODO: adjust hotness here
            # add to the user's item pool
            users.update(
                {'_id': _id},
                {'$push': {'items': short_item}},
            )

            # add the price back in so we'll have it for the ledger
            short_item['price'] = price
            added.append(short_item)

    # TODO: do something with errored items here?
    mongo.db.ledger.insert({
        'user_id': _id,
        'items': added,
        'change': -sum(item['price'] for item in added),
        'previous': previous_gold,
        'time': time.time(),
    })
    return True, 'success'