Skip to content

RentOne Commerce Service — Business Flow Documentation

Service: commerce-service
Port: 6008
Stack: Spring Boot 3.5.6 · Java 21 · MongoDB · Eureka · OpenFeign
Architecture: Multi-tenant, JWT-authenticated REST microservice


Service Overview

The Commerce Service is the transactional core of the RentOne platform. It owns the full rental lifecycle: browsing intent (wishlist) → selection (cart) → pricing → checkout → payment → fulfilment (delivery) → ongoing subscription billing → invoicing and history. All data is tenant-isolated; the JWT filter resolves the correct MongoDB connection per tenant on every request.

Infrastructure Topology

Client → API Gateway → commerce-service (:6008)
                           │
          ┌────────────────┼─────────────────────┐
          ▼                ▼                     ▼
  rentone-product-catalog  payment-gateway  notifications
          ▼                                     ▼
  inventory-system                       operation-service
          ▼
  rentone-users

MongoDB Collections

Collection Description
user_carts Active shopping carts per user/tenant
users_wishlist Saved wishlist items per user
user_addresses User delivery addresses (geo-indexed)
order_draft Pre-payment checkout snapshots
orders Confirmed rental orders + subscription state
delivery_assignments Delivery partner assignments
invoices Invoice records with URLs
order_history Immutable audit trail of order state changes
db_sequences MongoDB-based auto-increment counters

1. Customer Cart Flow

Flow Description

A customer adds rental items (variants or pre-configured packages) to their cart. The cart is created on first add. Each save recalculates a live pricing summary. The cart persists until an order is placed and payment succeeds, at which point it is deleted.

REST Endpoints

Method Path Description
POST /cart/v1/add Add item to cart
PUT /cart/remove-item Remove a single cart item
PUT /cart/update/quantity-and-tenure Update quantity or rental tenure
GET /cart/get/by-user-id Retrieve full cart
POST /cart/pricing/preview Preview pricing without persisting
GET /cart/check-exist-in-cart Single item existence check
GET /cart/check-exist-in-cart/bulk Bulk existence check

Business Rules

  • One cart per (userId, tenantId) combination. A second add merges quantities if the same (itemType, variantId/packageId, selectedTenure) already exists.
  • PACKAGE items require both packageId and selectedTenure. The price is fetched live from rentone-product-catalog and must match an active package's TenurePricing map.
  • VARIANT items require variantId and must carry a pricePerMonth.
  • Removing the last item from a cart deletes the cart document entirely.
  • Setting quantity ≤ 0 on update is treated as a remove.
  • Pricing is recalculated and persisted on every mutating operation.

Validation Rules

  • itemType is mandatory on add.
  • packageId required when itemType = PACKAGE.
  • selectedTenure required when itemType = PACKAGE; must exist in the package's tenurePricing map.
  • variantId required when itemType = VARIANT.
  • Package must be active = true.
  • quantity defaults to 1 if null.

Flowchart

flowchart TD
    A[Customer] --> B[Add Item to Cart]
    B --> C[Validate Request]
    C --> D{Cart Exists?}
    D -- No --> E[Create New Cart]
    D -- Yes --> F[Load Existing Cart]
    E --> G{Package Item?}
    F --> G
    G -- Yes --> H[Fetch Package & Validate Tenure]
    G -- No --> I[Use Variant Details]
    H --> J{Duplicate Item?}
    I --> J
    J -- Yes --> K[Merge Quantity]
    J -- No --> L[Add New Item]
    K --> M[Recalculate Pricing]
    L --> M
    M --> N[Save Cart]
    N --> O[Return Success]

Data Flow Diagram

CartItemRequest ──► CartService ──► [ProductCatalog if PACKAGE]
                                  │
                                  ├──► merge/add CartItem to cart.items[]
                                  │
                                  └──► PricingEngine.calculatePricing()
                                              │
                                              └──► save Cart to user_carts

External Service Dependencies

  • rentone-product-catalogGET /product/packages/get/by-id (PACKAGE adds and quantity/tenure updates)

Error Scenarios

Scenario Response
itemType missing false, "ItemType required"
Package not found in catalog false, "Package not found"
Package inactive false, "Package not active"
Invalid tenure for package false, "Invalid tenure for package"
variantId missing for VARIANT false, "VariantId required"
Cart not found on remove/update false, "Cart not found"
Cart item not found false, "Cart item not found"

2. Customer Wishlist Flow

Flow Description

Customers save items for later consideration. A wishlist is created on first add. Items can be moved directly to the cart in bulk. Empty wishlists are automatically deleted.

REST Endpoints

Method Path Description
POST /wishlist/add Add item to wishlist
DELETE /wishlist/remove/item Remove item from wishlist
GET /wishlist/get Retrieve full wishlist
POST /wishlist/move-to-cart Move selected items to cart
GET /wishlist/check-exist-in-wishlist Single item check
GET /wishlist/check-exist-in-wishlist/bulk Bulk existence check

Business Rules

  • One wishlist per userId. Wishlists are not tenant-scoped.
  • Duplicate detection: for PACKAGE items, match on packageId; for VARIANT items, match on variantId.
  • Adding a VARIANT triggers recordWishlist() on rentone-product-catalog for popularity tracking.
  • move-to-cart processes each selected wishlistItemId, calls CartService.addToCart() for each, then removes successfully moved items from the wishlist.
  • If the wishlist becomes empty after remove or move, it is deleted.

Validation Rules

  • Duplicate items are rejected: false, "Item already exists in wishlist".
  • Move-to-cart with no wishListItemIds is rejected: false, "No wishlist items selected".
  • wishlistItemId that does not exist is silently skipped during bulk move.

Flowchart

flowchart TD
    A[Customer] --> B{Action}
    B -- Add Item --> C[Load or Create Wishlist]
    C --> D{Already in Wishlist?}
    D -- Yes --> E[Reject Duplicate]
    D -- No --> F[Save Item to Wishlist]
    F --> G{Variant Item?}
    G -- Yes --> H[Record Wishlist Stat in Catalog]
    G -- No --> I[Done]
    H --> I
    B -- Move to Cart --> J[Load Wishlist]
    J --> K[Add Each Selected Item to Cart]
    K --> L[Remove Moved Items from Wishlist]
    L --> M{Wishlist Empty?}
    M -- Yes --> N[Delete Wishlist]
    M -- No --> O[Save Wishlist]

MongoDB Collections Used

  • users_wishlist

External Service Dependencies

  • rentone-product-catalogPOST /variant-stats/record-wishlist (VARIANT adds only)

Error Scenarios

Scenario Response
Item already in wishlist false, "Item already exists in wishlist"
Wishlist not found on remove false, "Wishlist is empty"
Item not found on remove false, "Item not found in wishlist"
Empty wishlist on move false, "Wishlist is empty"
No item ids on move false, "No wishlist items selected"

3. Address Management Flow

Flow Description

Customers manage delivery addresses. Each address stores geospatial coordinates (GeoJsonPoint) and a Google Places reference. The first address saved is automatically marked as default. Marking a new address as default unsets the previous default.

REST Endpoints

Method Path Description
POST /addresses/save Create address
PUT /addresses/update Update existing address
DELETE /addresses/delete Delete address by id
GET /addresses/get-all Paginated list by userId
GET /addresses/get/by-user-and-address-id Single address lookup
GET /addresses/get/default Get default address

Business Rules

  • Address ID is a Long generated via SequenceGeneratorService (MongoDB counter: address_sequence).
  • If a user has no existing addresses, the new address is forced to defaultAddress = true.
  • Switching default: the existing default is set to false before the new one is set to true.
  • saveInternal is used by bulk upload flows; same validation, no HTTP request object required.
  • GeoJsonPoint uses [longitude, latitude] ordering (GeoJSON standard).

Validation Rules

Required fields on save: userId, name, phone, line1, city, state, pincode. Missing any required field → false, "Required Fields Missing".

Flowchart

flowchart TD
    A[Customer] --> B[Submit Address]
    B --> C[Validate Required Fields]
    C --> D{First Address?}
    D -- Yes --> E[Force Set as Default]
    D -- No --> F{Mark as Default?}
    F -- Yes --> G[Unset Previous Default]
    F -- No --> H[Keep Existing Default]
    G --> I[Generate Address ID]
    E --> I
    H --> I
    I --> J[Save Address]
    J --> K[Return Saved Address]

MongoDB Collections Used

  • user_addresses (geo-spatial index on location)
  • db_sequences (counter: address_sequence)

External Service Dependencies

  • operation-serviceGET /maps/place-details (used for Google Maps place resolution, called optionally via OperationServiceProxy)

Error Scenarios

Scenario Response
Required field missing false, "Required Fields Missing"
Address not found on update false, "Address Not Found"
Address not found on delete false, "Address Not Found"
No addresses found false, "Address Not Found"
Default address not found false, "Default Address Not Found"

4. Order Draft Flow

Flow Description

An Order Draft is a pre-payment snapshot of the intended order. It is created during checkout, holds all order items (including expanded package variants), the chosen delivery address (embedded), and a computed pricing summary. It is the bridge between the cart and the payment gateway. The draft is deleted once payment succeeds and the real order is persisted.

Business Rules

  • Draft ID is a UUID string.
  • The cart must not be empty.
  • A valid delivery address must be selected.
  • payableNow must be > 0; otherwise checkout is rejected.
  • PACKAGE cart items: package details are fetched from rentone-product-catalog and each PackageItem is snapshotted into PackageVariantSnapshot.
  • Non-package items get a tenure adjustment applied to finalPricePerMonth:
  • 3 months: +20%
  • 6 months: +10%
  • 12 months: 0% (baseline)
  • 18 months: -10%
  • 24 months: -20%
  • PACKAGE prices are not tenure-adjusted at draft time (already adjusted at catalog level).
  • Draft initial status: PENDING_PAYMENT.

Flowchart

flowchart TD
    A[Customer Initiates Checkout] --> B[Load Customer Cart]
    B --> C{Cart Empty?}
    C -- Yes --> D[Reject: Cart Empty]
    C -- No --> E[Load Delivery Address]
    E --> F{Address Valid?}
    F -- No --> G[Reject: No Address]
    F -- Yes --> H[Map Cart Items to Order Items]
    H --> I[Apply Tenure Price Adjustment]
    I --> J{Package Item?}
    J -- Yes --> K[Fetch & Snapshot Package Variants]
    J -- No --> L[Use Variant Details]
    K --> M[Calculate Pricing Summary]
    L --> M
    M --> N{Payable Amount Valid?}
    N -- No --> O[Reject: Invalid Pricing]
    N -- Yes --> P[Save Order Draft]
    P --> Q[Return Draft to Checkout]

MongoDB Collections Used

  • order_draft

External Service Dependencies

  • rentone-product-catalogGET /product/packages/get/by-id (for each PACKAGE cart item)

Error Scenarios

Scenario Response
Cart empty or not found false, "Cart is empty or not found"
Address not selected false, "Please select a delivery address"
Package not found in catalog RuntimeException: "Package not found while creating draft"
Pricing is zero or invalid false, "Invalid pricing. Please try again."
Draft not found on fetch false, "Draft not found"

5. Order Creation Flow

Flow Description

Order creation is driven by payment verification. After the customer completes payment via the gateway, the gateway webhook calls /orders/payment/status. The service verifies the amount, creates the Orders document, expands cart items by quantity (each physical unit becomes a distinct OrderItem), records order stats to the product catalog, initialises order history, deletes the cart and draft, and fires notifications.

REST Endpoints

Method Path Description
POST /orders/checkout Initiate checkout (create draft + payment intent)
POST /orders/payment/status Payment gateway callback
POST /orders/cancel Cancel a confirmable order
POST /orders/payment/manual Record manual/offline payment
GET /orders/get/by-user-id Customer order history
GET /orders/get/all Admin paginated order list
GET /orders/get/by-id Single order detail (with delivery/history)
GET /orders/get/active-rentals Active subscriptions for a user
GET /orders/get/overdue-orders All overdue orders (scheduled task use)

Business Rules

  • Order ID format: generated by OrderIdGeneratorUtil (custom format, not UUID).
  • Idempotency: existByCartId(cartId) check prevents duplicate orders from duplicate callbacks.
  • Amount verification: payableNow from draft must exactly match response.amount; mismatch throws exception.
  • Payment failure: draft status set to PAYMENT_FAILED, no order created.
  • On success: items are expanded by quantity — each unit gets a new UUID cartItemId. PACKAGE items are further expanded per PackageItem × quantity.
  • productCatalogProxy.recordOrder() is called for every expanded variant to update inventory stats.
  • Initial subscription: billingCycle = MONTHLY, nextPaymentDate = +1 month, subscriptionStatus is set to ACTIVE on delivery.
  • Cancellable statuses: PAID, CONFIRMED, SCHEDULED. Cancellation triggers paymentGatewayProxy.refundPayment().
  • Cart and draft documents are deleted after successful order creation.

Validation Rules

  • payableNow amount must match payment callback amount exactly.
  • Order must exist for cancellation; must be in a cancellable status.
  • Cancellation requires at least one PaymentStatus.SUCCESS payment record.

Flowchart

flowchart TD
    A[Customer Checks Out] --> B[Create Order Draft]
    B --> C[Initiate Payment via Gateway]
    C --> D[Return Payment Intent to Customer]
    D --> E[Customer Completes Payment]
    E --> F[Gateway Sends Payment Result]
    F --> G{Duplicate Order?}
    G -- Yes --> H[Return Already Processed]
    G -- No --> I{Payment Successful?}
    I -- No --> J[Mark Draft as Failed]
    I -- Yes --> K[Verify Amount Match]
    K --> L[Create Order Record]
    L --> M[Expand Items by Quantity]
    M --> N[Record Stats in Product Catalog]
    N --> O[Create Order History]
    O --> P[Delete Cart & Draft]
    P --> Q[Notify Customer]

MongoDB Collections Used

  • order_draft (read + delete)
  • user_carts (delete)
  • orders (create)
  • order_history (create)

External Service Dependencies

  • payment-gatewayPOST /rentone/payment-gateway/payment/initiate
  • payment-gatewayPOST /rentone/payment-gateway/refund-payment (on cancel)
  • rentone-product-catalogPOST /variant-stats/record-order
  • notificationsPOST /app-notifications/create

Error Scenarios

Scenario Response
Cart empty RuntimeException from draft creation
Amount mismatch RuntimeException: "Payable amount mismatch"
Duplicate callback true, "Order already processed"
Draft not found on callback RuntimeException: "Draft not found"
Order not found on cancel false, "Order not found"
Non-cancellable status false, "Order cannot be cancelled when status is X"
No successful payment for refund false, "Payment record not found for order"
Refund initiation failed false, "Refund initiation failed"

6. Pricing Calculation Flow

Flow Description

Pricing is computed by DefaultPricingEngine on every cart mutation, at draft creation, and on demand via the preview endpoint. It produces a CartPricing object covering checkout amounts, recurring monthly amounts, GST, deposit, and delivery charge.

Business Rules

Tenure-based price adjustments (VARIANT items only):

Tenure (months) Adjustment
3 +20%
6 +10%
12 0% (baseline)
18 -10%
24 -20%

GST: 18% GST is baked into the monthly rent. Extracted as: GST = amount - (amount / 1.18).

Delivery charge: Free if monthlyRent ≥ ₹500; otherwise ₹500 flat.

Deposit: Sum of depositAmount × quantity across all items.

payableNow = monthlyRent (first month paid at checkout; deposit is tracked separately via DepositInfo).

Estimated delivery: current date + 3 days.

Overdue penalty: - 1–5 days overdue: flat ₹100 - Beyond 5 days: ₹100 × (floor(daysOverdue / 30) + 1) (i.e. ₹100 per month, minimum ₹100)

Recalculation on item return/maintenance: updateOrderItemsBillingStatus marks individual OrderItem.active = false, recalculates monthly pricing based only on active items, and updates SubscriptionStatus accordingly.

Flowchart

flowchart TD
    A[Cart Items] --> B[Calculate Monthly Rent per Item]
    B --> C{Item Type?}
    C -- Variant --> D[Apply Tenure Adjustment]
    C -- Package --> E[Use Price As-Is]
    D --> F[Sum Total Monthly Rent]
    E --> F
    F --> G[Extract 18% GST from Total]
    F --> H{Total Under ₹500?}
    H -- Yes --> I[Add ₹500 Delivery Charge]
    H -- No --> J[Free Delivery]
    F --> K[Sum Deposit Amount]
    G --> L[Build Pricing Summary]
    I --> L
    J --> L
    K --> L
    L --> M[Return CartPricing]

Data Flow Diagram

List<CartItem>
     │
     ▼
[Per item: pricePerMonth × quantity] ──── VARIANT: apply tenure adjustment
                                     ──── PACKAGE: no adjustment
     │
     ▼
totalMonthlyRent
     ├──► gstAmount  = total − (total / 1.18)
     ├──► payableNow = totalMonthlyRent
     └──► deliveryCharge = (total < 500) ? 500 : 0
totalDeposit = Σ(depositAmount × quantity)

Error Scenarios

Scenario Behaviour
pricePerMonth is null Item skipped in calculation
quantity is null or ≤ 0 Item skipped
VARIANT with null selectedTenure Item skipped (no tenure = no adjustment, item excluded)
Empty cart All fields return "0"

7. Rental Subscription Flow

Flow Description

After an order is delivered, its subscriptionStatus is set to ACTIVE. Each month the customer pays their monthlyPayable. Overdue detection runs via a scheduled task that queries findActiveOrdersBeforeDate(today). Overdue orders accumulate a penalty added to the next payment. Manual payments (cash/offline) are recorded via an admin endpoint.

REST Endpoints

Method Path Description
POST /orders/payment/monthly Initiate monthly rent payment
POST /orders/payment/status Gateway callback (shared, moduleName = RENTAL_MONTHLY)
POST /orders/payment/manual Record manual payment
GET /orders/get/overdue-orders List overdue subscriptions (public, no auth)
GET /orders/get/active-rentals Customer's active rentals

Subscription Status Values

Status Meaning
ACTIVE Paid and current
OVERDUE Payment due date passed
PAUSED All items returned/inactive
CANCELLED Order cancelled
COMPLETED Tenure expired

Business Rules

  • nextPaymentDate advances by exactly 1 calendar month on each successful payment.
  • Penalty is applied only when System.currentTimeMillis() > nextPaymentDate.getTime().
  • failedPaymentCount increments on failed gateway attempts; resets to 0 on success.
  • overdueNotified flag prevents duplicate overdue notifications; reset to false on payment.
  • Manual payments use transaction ID prefix API_MONTHLY_ + timestamp; these are excluded from the monthly payment dashboard "paid" totals.
  • CSV-imported payments use prefix CSV_; also excluded from dashboard.
  • updateOrderItemsBillingStatus is called by the Operations service when items are returned or placed under maintenance to recalculate billing from active items only.

Flowchart

flowchart TD
    A[Customer Pays Monthly Rent] --> B[Load Active Order]
    B --> C{Payment Overdue?}
    C -- Yes --> D[Calculate Penalty]
    C -- No --> E[No Penalty]
    D --> F[Total = Monthly Rent + Penalty]
    E --> F
    F --> G[Initiate Payment via Gateway]
    G --> H[Customer Completes Payment]
    H --> I{Payment Successful?}
    I -- No --> J[Record Failed Attempt]
    I -- Yes --> K[Append Payment Record]
    K --> L[Advance Next Payment Date +1 Month]
    L --> M[Reset Overdue Flags]
    M --> N[Mark Subscription Active]

MongoDB Collections Used

  • orders

External Service Dependencies

  • payment-gatewayPOST /rentone/payment-gateway/payment/initiate
  • payment-gateway — callback to /orders/payment/status

Error Scenarios

Scenario Response
Order not found RuntimeException: "Order not found for monthly payment"
Amount mismatch RuntimeException: "Monthly rent mismatch"
Payment gateway failure false, "Monthly payment failed"

8. Delivery Assignment Flow

Flow Description

Once an order reaches CONFIRMED status, an admin or the system assigns it to a delivery partner. The assignment progresses through ASSIGNED → OUT_FOR_DELIVERY → DELIVERED. Each stage transition updates both the delivery_assignments collection and the parent orders.status via OrderStatusSyncService, and fires push notifications to the partner and customer.

Business Rules

  • Only CONFIRMED orders can be assigned.
  • Duplicate assignment is prevented by checking if a DeliveryAssignment already exists for the orderId.
  • Reassignment is only allowed when current status is ASSIGNED; cannot reassign to the same partner.
  • Status progression is strictly linear: ASSIGNED → OUT_FOR_DELIVERY → DELIVERED.
  • A DELIVERED or CANCELLED assignment cannot be advanced.
  • assignType is MANUAL (admin-assigned) or AUTOMATIC (system-assigned).
  • Address is snapshotted from the order's EmbeddedAddress at time of assignment.
  • OrderStatusSyncService maps assignment statuses to order statuses:
  • ASSIGNEDOrderStatus.SCHEDULED
  • OUT_FOR_DELIVERYOrderStatus.OUT_FOR_DELIVERY
  • DELIVEREDOrderStatus.DELIVERED + subscriptionStatus = ACTIVE

Flowchart

flowchart TD
    A[Admin Assigns Order to Partner] --> B{Order Status Confirmed?}
    B -- No --> C[Reject: Must be Confirmed]
    B -- Yes --> D{Already Assigned?}
    D -- Yes --> E[Reject: Duplicate Assignment]
    D -- No --> F[Create Delivery Assignment]
    F --> G[Notify Delivery Partner]
    G --> H[Partner Updates Status]
    H --> I{Current Status?}
    I -- Assigned --> J[Mark Out for Delivery]
    I -- Out for Delivery --> K[Mark Delivered]
    J --> L[Sync Order Status]
    K --> M[Activate Subscription]
    L --> N[Update Order History]
    M --> N
    N --> O[Notify Customer]

MongoDB Collections Used

  • delivery_assignments
  • orders
  • order_history

External Service Dependencies

  • notificationsPOST /app-notifications/create (ORDER_ASSIGNED, OUT_FOR_DELIVERY, ORDER_DELIVERED)

Error Scenarios

Scenario Response
Order not CONFIRMED false, "Order must be CONFIRMED before assignment"
Duplicate assignment false, "Order Already Assigned"
Assignment not found on reassign false, "Delivery Assignment Not Found"
Reassign to same partner false, "cannot be re-assigned to the same partner"
Non-ASSIGNED status on reassign false, "Cannot reassign order in X state"
Assignment not found on update false, "Delivery Assignment Not found"
Already delivered false, "Order is already delivered"
Assignment cancelled false, "Cannot update status of a cancelled assignment"
Invalid status transition false, "Cannot move to OUT_FOR_DELIVERY from X"

9. Invoice Generation Flow

Flow Description

Invoices are generated externally (PDF likely by a batch/admin process) and their URLs are stored in the invoices collection. The Commerce Service provides CRUD endpoints and a bulk URL lookup used to enrich order list responses with invoice links.

REST Endpoints (via InvoiceController)

Method Path Description
POST /invoices/save Persist invoice URL for an order
GET /invoices/get/by-order-id Retrieve invoice URL by orderId
GET /invoices/get/all Paginated admin invoice list

Invoice ID Format

INV + yyyyMMdd + auto-increment sequence number
Example: INV202406240042

Business Rules

  • Invoice ID is generated by SequenceGeneratorService using counter invoice_sequence.
  • One invoice per order. The invoice URL is a hosted file link (S3/CDN).
  • Order lists (getAllOrders, getActiveRentals) automatically hydrate invoiceUrl on each order via a bulk getInvoiceUrlsByOrderIds() call.
  • Date filtering uses dd-MM-yyyy HH:mm format (Asia/Kolkata timezone).

Flowchart

flowchart TD
    A[Admin Saves Invoice URL] --> B[Generate Invoice ID]
    B --> C[Format: INV + Date + Sequence]
    C --> D[Save Invoice Record]
    D --> E[Return Invoice Response]
    F[Order List Request] --> G[Collect Order IDs]
    G --> H[Bulk Lookup Invoice URLs]
    H --> I[Attach URL to Each Order]
    I --> J[Return Enriched Order List]
    K[Customer Requests Invoice] --> L{Invoice Exists?}
    L -- Yes --> M[Return Invoice URL]
    L -- No --> N[Return Not Found]

MongoDB Collections Used

  • invoices
  • db_sequences (counter: invoice_sequence)

External Service Dependencies

None — invoice PDF generation is external to this service.

Error Scenarios

Scenario Response
Invoice not found by orderId false, "Invoice Not Found"
No invoices in search result false, "Invoices Not Found"

10. Order History Flow

Flow Description

OrderHistory is an immutable audit log created at order placement and extended at every status change. It records who made the change, when, why, and what delivery partner (if any) was involved. It is the source of truth for order tracking.

Business Rules

  • History document ID: "HIS-" + orderId.
  • Each OrderStageMgmt entry tracks: status, isCurrentStatus, changedAt, updatedBy, reason, assignType, deliveryPartnerId.
  • On each stage add, the previous current stage's isCurrentStatus is set to false.
  • Created at order placement with status PAID, updatedBy = SYSTEM_USER.
  • Subsequently added by OrderStatusSyncService on each delivery assignment transition.

REST Endpoints

Method Path Description
GET /order-history/get/by-order-id Full history for an order
GET /orders/track/{orderId} Customer-facing order tracking

Flowchart

flowchart TD
    A[Order Placed] --> B[Create History Record]
    B --> C[Record Initial Stage: PAID]
    C --> D[Save Order History]
    E[Status Change Event] --> F[Load Order History]
    F --> G[Mark Previous Stage Inactive]
    G --> H[Append New Stage]
    H --> I[Record Who Changed & Why]
    I --> J[Save Updated History]
    K[Customer Tracks Order] --> L[Load Order History]
    L --> M[Return All Stages in Sequence]

MongoDB Collections Used

  • order_history

External Service Dependencies

None.

Error Scenarios

Scenario Response
History not found on fetch false, "Order History not found"
History not found on addStage false, "Order History not found"
Track — history not found false, "Order History not fount"


Cross-Cutting Concerns

Authentication & Multi-Tenancy

All requests require an X-Tenant-ID header. The JwtAuthenticationFilter resolves the tenant's MongoDB connection string (from a tenant registry service, cached in-memory per JVM), sets it on a thread-local MongoConnectionStorage, and clears it after the request. Protected routes additionally require a Bearer token in the Authorization header.

Public (unauthenticated) endpoints: - GET /orders/get/overdue-orders - POST /cart/pricing/preview - GET /cart/check-exist-in-cart - GET /wishlist/check-exist-in-wishlist

Error Reporting

MainExceptionHandler is a global @ControllerAdvice that: 1. Prints the stack trace. 2. Finds the first stack frame within the RentOne package to extract filename and line number. 3. Constructs an ErrorContext and calls notificationsProxy.reportError() to the Notifications service. 4. Returns 500 INTERNAL_SERVER_ERROR with { success: false, message: "Something went wrong" }.

Sequence ID Generation

SequenceGeneratorService uses MongoDB's findAndModify with upsert: true to atomically increment a counter in the db_sequences collection. Used for: address_sequence, invoice_sequence, delivery_assignment_sequence.


Full Entity Reference

Orders (collection: orders)

id                  String          Custom order ID (OrderIdGeneratorUtil)
tenantId            String
userId              String
cartId              String          Reference to source cart
items               OrderItem[]     Expanded by quantity
address             EmbeddedAddress Snapshot at order time
shippingMethod      String
pricingSummary      CartPricing     Snapshot at checkout
depositInfo         DepositInfo     Cash/offline deposit tracking
billingCycle        MONTHLY
subscriptionStatus  ACTIVE | PAUSED | CANCELLED | COMPLETED | OVERDUE
nextPaymentDate     Date            Advances +1 month per payment
failedPaymentCount  int
overdueNotified     boolean
reminderNotified    boolean
lastPaymentAttempt  Date
paymentInfo         PaymentInfo[]   Appended on each payment
status              OrderStatus     (see enum below)
remark              String
createdAt / updatedAt Date
invoiceUrl          @Transient (hydrated at read time)

OrderItem (embedded in Orders and OrderDraft)

cartItemId          String  (UUID per unit after expansion)
itemType            PACKAGE | VARIANT
packageId           Long
packageItems        PackageVariantSnapshot[]
variantId           Long
productId           Long
variantSku          String
variantName         String
pricePerMonth       String   Catalog base price
finalPricePerMonth  String   After tenure adjustment
adjustmentAmount    String   Adjustment delta
depositAmount       String
quantity            Integer  Always 1 after expansion
selectedTenure      Long     Months
itemValidTill       Date
active              boolean  false = excluded from billing
image               String

CartPricing (embedded pricing object)

deposit             String
deliveryCharge      String
payableNow          String   = monthlyRent (charged at checkout)
monthlyRent         String
gstAmount           String   18% extracted from monthlyRent
monthlyPayable      String   = monthlyRent
discount            String   Tenure adjustment total
couponApplied       String   (reserved, not implemented)
estimatedDeliveryDate Date   +3 days from calculation
penalty             @Transient computed at read time

Order Status State Machine

DRAFT → PENDING_PAYMENT → PAYMENT_FAILED
                        → PAID → CONFIRMED → SCHEDULED → OUT_FOR_DELIVERY → DELIVERED
                        → CANCELLED → REFUNDED

Delivery Assignment Status Machine

ASSIGNED → OUT_FOR_DELIVERY → DELIVERED
         → CANCELLED

External Microservice Dependency Map

Proxy Service Name (Eureka) Key Calls from Commerce
ProductCatalogProxy rentone-product-catalog Get package by ID, record-order, record-wishlist, get variant/product/category maps
PaymentGatewayProxy payment-gateway Initiate payment, refund payment
NotificationsProxy notifications Report error, create push notifications
OperationServiceProxy operation-service Get delivery partner by ID, get place details, get return/maintenance active order IDs
InventoryProxy inventory-system Bulk upload inventory items (bulk order import)
UsersProxy rentone-users Create internal users, get total user count, submit KYC

Document generated from source analysis of commerce-service v0.0.1-SNAPSHOT · Spring Boot 3.5.6 · Java 21