Aller au contenu principal

Cart Data Management

Overview

The cart system now separates reference data from snapshot data to prevent duplication while maintaining historical accuracy for paid orders.

Structure

Cart (Reference Only)

Used for unpaid commands. Contains only references to products and quantities:

{
products: [
{
product_id: ObjectId,
quantity: number
}
]
}

CartSnapshot (Historical Data)

Automatically created when a command is marked as paid. Stores immutable pricing data:

{
products: [
{
product_id: ObjectId,
title: string,
price: number,
quantity: number
}
],
totalPrice: number
}

Usage

Creating a Command

When creating a command, only store product IDs and quantities:

const command = await Command.create({
// ... other fields
cart: {
products: [
{ product_id: "...", quantity: 2 },
{ product_id: "...", quantity: 1 }
]
},
paid: false
});

Marking as Paid

Use the service to automatically create a snapshot:

import commandService from '../services/command.service';

// This creates the snapshot and marks as paid
const paidCommand = await commandService.markAsPaid(commandId);

Displaying Cart Data

The service handles both paid and unpaid commands:

import commandService from '../services/command.service';

// Returns current pricing for unpaid, snapshot for paid
const cartData = await commandService.getCartWithPricing(command);

// cartData will have { products: [...], totalPrice: number }

Example: Payment Webhook

app.post('/webhook/stripe', async (req, res) => {
const { commandId } = req.body;

// Mark as paid - automatically creates snapshot
await commandService.markAsPaid(commandId);

res.status(200).send('OK');
});

Benefits

No duplication for unpaid carts - prices always reflect current product data ✅ Historical accuracy for paid orders - prices frozen at payment time ✅ Automatic snapshots - service handles snapshot creation ✅ Consistent API - same method for both paid/unpaid display logic

Migration Note

Existing commands with old cart structure will need migration. The cartSnapshot field is optional, so the system remains backward compatible.