Key Components:
- API Endpoints:
- POST
/cart/add
: Adds items to a cart. - POST
/cart/checkout/initiate
: Initiates the checkout process for a cart. - POST
/checkout/submit
: Submits lead to OMS service.
- POST
- Data Models:
- AddCartItemRequest: The incoming request model for adding items to the cart.
- CartItem: Represents an item in the cart.
- Cart: Represents the entire cart with items and metadata.
- CartStatus: Enum representing the status of the cart (e.g., ACTIVE, EXPIRED, CHECKOUT_INITIATED).
- Services and Processes:
- Validation: Ensures that incoming requests meet certain criteria.
- Cart Persistence: Saving and updating cart information in MongoDB.
- Configurator Service: Fetches vehicle details and pricing summaries.
- Checkout Lock Mechanism: Uses Redis to lock the cart during checkout initiation to prevent concurrent modifications.
- Versioning: Manages cart versions to handle deletions, only the customer with most recent cart version will be able to delete the configs.
- (NOT Implemented) Versioning and Concurrency Control: Manages cart versions to handle concurrent updates, especially when carts are shared via URLs.
- Repositories:
- CartMongoRepository: Interface to interact with MongoDB for cart data.
- CheckoutRepository: Stores checkout-related data like cartId, requestId, and uuid.
Data Flow Steps
Adding Items to Cart (POST /cart/add):
- Request Validation:
- Validate the incoming AddCartItemRequest.
- Check for null or invalid values (e.g., vehicle quantity, configuration details).
- Transforming Request:
- Convert AddCartItemRequest into CartItem for persistence.
- Perform additional validation on CartItem.
- Fetching Vehicle Details:
- Since the frontend doesn’t provide vehicle details and pricing summary, make a call to the Configurator Service to fetch these details based on the vehicle’s configuration.
- Determine Cart Creation or Update:
- If cartId is null in the request:
- Attempt to retrieve an existing cart using the uuid.
- If a cart exists, check its status:
- If status is CHECKOUT_INITIATED, verify if the checkout has expired using validateCheckoutTTLExpiredStatus() and revert to ACTIVE if necessary.
- If the cart is not active or cannot be updated, throw an exception.
- If no existing cart is found or cannot be used, create a new cart:
- Generate a new cartId (8 characters long).
- Set cart status to ACTIVE.
- Assign a version number (random UUID).
- Set the cart expiry to 180 days.
- Save the cart in MongoDB.
- If cartId is provided and valid:
- Append items to the existing cart after validating its active status.
- If cartId is null in the request:
- Version Management:
- Use version numbers to handle deletions:
- When carts are shared via URLs, multiple users might attempt to update the same cart.
- If a cart’s version number has changed due to another user’s update, now since the another user has the most recent version only they’ll be able to delete the configs in cart.
- (NOT IMPLEMENTED) Use version numbers to handle concurrency:
- When carts are shared via URLs, multiple users might attempt to update the same cart.
- If a cart’s version number has changed due to another user’s update, prevent conflicting updates by checking version mismatches.
- Use version numbers to handle deletions:
Initiating Checkout (POST /cart/checkout/initiate):
- Request Validation
- Validate the incoming cartCheckoutRequest.
- Extract cartId and uuid.
- Cart Retrieval and Validation
- Retrieve the cart from CartMongoRepository using cartId and uuid.
- Validate the cart’s status and contents.
- Lock Acquisition using Redis:
- Purpose: Prevent multiple checkout initiations on the same cart concurrently.
- Process:
- Obtain a Redis template from the cacheFactory.
- Check if a lock key exists for the cart:
- If the key exists (non-negative expiry time), the cart is already locked; throw a CartCacheException.
- If not, set a lock key with an expiry time (e.g., 10 minutes).
- The lock ensures that the checkout process has exclusive access to the cart for a limited time.
- Updating Cart Status and Checkout Response:
- Change the cart status to CHECKOUT_INITIATED.
- Prepare checkoutResponse with:
- refreshWindowSize: e.g., 2 minutes.
- remainingTime: e.g., 10 minutes.
- requestId: unique identifier for the checkout session.
- Save checkout details in CheckoutRepository for later validation and cleanup.
- Return Response:
- Send the checkoutResponse back to the client, indicating that the checkout process has been initiated successfully.
Checkout Submit (POST /checkout/submit)
Submits all the details to OMS service which returns the orderId.
Sequence Diagrams
ADD API
sequenceDiagram
participant Client
participant CartService
participant ConfiguratorService
participant MongoDB
Client ->> CartService: POST /cart/add (AddCartItemRequest)
Note over CartService: Validate AddCartItemRequest
CartService ->> CartService: Transform to CartItem
CartService ->> CartService: Validate CartItem
CartService ->> ConfiguratorService: Fetch vehicle details & pricing
ConfiguratorService -->> CartService: VehicleDetails, PriceSummary
alt cartId is null
CartService ->> MongoDB: Retrieve cart by uuid
alt Cart exists
CartService ->> CartService: checkCartActiveStatus()
alt Cart status is CHECKOUT_INITIATED
CartService ->> CartService: validateCheckoutTTLExpiredStatus()
alt Checkout expired
CartService ->> CartService: Revert cart status to ACTIVE
else Checkout active
CartService ->> Client: Throw Exception (Cart Locked)
Note over CartService: Operation aborted
end
else Cart is ACTIVE
CartService ->> MongoDB: Append items to cart
CartService ->> MongoDB: Update cart in database
end
else Cart does not exist
CartService ->> CartService: generateCartId()
CartService ->> CartService: Set cart status to ACTIVE
CartService ->> CartService: Set version number
CartService ->> CartService: Set cart expiry (180 days)
CartService ->> MongoDB: Save new cart
end
else cartId is provided
CartService ->> MongoDB: Retrieve cart by cartId
CartService ->> CartService: checkCartActiveStatus()
alt Cart is ACTIVE
CartService ->> MongoDB: Append items to cart
CartService ->> MongoDB: Update cart in database
else
CartService ->> Client: Throw Exception (Cart not active)
Note over CartService: Operation aborted
end
end
CartService ->> Client: Return response (Cart updated)
Checkout Initiate
sequenceDiagram
participant Client
participant CartService
participant MongoDB
participant Redis
participant CheckoutRepository
Client ->> CartService: POST /cart/checkout/initiate (cartCheckoutRequest)
Note over CartService: Validate cartCheckoutRequest
CartService ->> MongoDB: Retrieve cart by cartId and uuid
CartService ->> CartService: Validate cart
CartService ->> Redis: Check if lock exists for cartId
alt Lock exists
Redis -->> CartService: Lock found
CartService ->> Client: Throw CartCacheException (Cart already in checkout)
Note over CartService: Checkout initiation failed
else Lock does not exist
Redis -->> CartService: No lock found
CartService ->> Redis: Set lock for cartId with expiry (10 mins)
CartService ->> CartService: Update cart status to CHECKOUT_INITIATED
CartService ->> MongoDB: Save cart with updated status
CartService ->> CheckoutRepository: Save checkout details (cartId, requestId, uuid)
CartService ->> Client: Return checkoutResponse (remainingTime, refreshWindowSize, requestId)
end