def lambda_handler()

in backend/shopping-cart-service/add_to_cart.py [0:0]


def lambda_handler(event, context):
    """
    Add a the provided quantity of a product to a cart. Where an item already exists in the cart, the quantities will
    be summed.
    """

    try:
        request_payload = json.loads(event["body"])
    except KeyError:
        return {
            "statusCode": 400,
            "headers": get_headers(),
            "body": json.dumps({"message": "No Request payload"}),
        }
    product_id = request_payload["productId"]
    quantity = request_payload.get("quantity", 1)
    cart_id, _ = get_cart_id(event["headers"])

    # Because this method can be called anonymously, we need to check there's a logged in user
    user_sub = None
    jwt_token = event["headers"].get("Authorization")
    if jwt_token:
        user_sub = get_user_sub(jwt_token)

    try:
        product = get_product_from_external_service(product_id)
        logger.info("No product found with product_id: %s", product_id)
    except NotFoundException:
        return {
            "statusCode": 404,
            "headers": get_headers(cart_id=cart_id),
            "body": json.dumps({"message": "product not found"}),
        }

    if user_sub:
        logger.info("Authenticated user")
        pk = f"user#{user_sub}"
        ttl = generate_ttl(
            7
        )  # Set a longer ttl for logged in users - we want to keep their cart for longer.
    else:
        logger.info("Unauthenticated user")
        pk = f"cart#{cart_id}"
        ttl = generate_ttl()

    if int(quantity) < 0:
        table.update_item(
            Key={"pk": pk, "sk": f"product#{product_id}"},
            ExpressionAttributeNames={
                "#quantity": "quantity",
                "#expirationTime": "expirationTime",
                "#productDetail": "productDetail",
            },
            ExpressionAttributeValues={
                ":val": quantity,
                ":ttl": ttl,
                ":productDetail": product,
                ":limit": abs(quantity),
            },
            UpdateExpression="ADD #quantity :val SET #expirationTime = :ttl, #productDetail = :productDetail",
            # Prevent quantity less than 0
            ConditionExpression="quantity >= :limit",
        )
    else:
        table.update_item(
            Key={"pk": pk, "sk": f"product#{product_id}"},
            ExpressionAttributeNames={
                "#quantity": "quantity",
                "#expirationTime": "expirationTime",
                "#productDetail": "productDetail",
            },
            ExpressionAttributeValues={
                ":val": quantity,
                ":ttl": generate_ttl(),
                ":productDetail": product,
            },
            UpdateExpression="ADD #quantity :val SET #expirationTime = :ttl, #productDetail = :productDetail",
        )
    metrics.add_metric(name="CartUpdated", unit="Count", value=1)

    return {
        "statusCode": 200,
        "headers": get_headers(cart_id),
        "body": json.dumps(
            {"productId": product_id, "message": "product added to cart"}
        ),
    }