first commit
This commit is contained in:
719
src/controllers/orderTrackingController.js
Normal file
719
src/controllers/orderTrackingController.js
Normal file
@@ -0,0 +1,719 @@
|
||||
// controllers/orderTrackingController.js
|
||||
|
||||
const { prisma } = require('../config/database');
|
||||
const {
|
||||
calculateDeliveryDate,
|
||||
getDeliveryEstimation,
|
||||
} = require('../services/deliveryEstimationService');
|
||||
|
||||
/**
|
||||
* @desc Get order tracking details
|
||||
* @route GET /api/orders/:orderId/tracking
|
||||
* @access Private
|
||||
*/
|
||||
exports.getOrderTracking = async (req, res, next) => {
|
||||
try {
|
||||
const { orderId } = req.params;
|
||||
const userId = req.user.id;
|
||||
|
||||
// Get order with all details
|
||||
const order = await prisma.order.findUnique({
|
||||
where: { id: orderId },
|
||||
include: {
|
||||
items: true,
|
||||
address: true,
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
phone: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!order) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'Order not found',
|
||||
});
|
||||
}
|
||||
|
||||
// Check if user owns this order
|
||||
if (order.userId !== userId) {
|
||||
return res.status(403).json({
|
||||
success: false,
|
||||
message: 'Unauthorized to view this order',
|
||||
});
|
||||
}
|
||||
|
||||
// Calculate delivery estimation
|
||||
const deliveryEstimation = await getDeliveryEstimation(
|
||||
order.address.postalCode,
|
||||
'STANDARD'
|
||||
);
|
||||
|
||||
// Get order timeline/history
|
||||
const timeline = generateOrderTimeline(order, deliveryEstimation.data);
|
||||
|
||||
// Get current status details
|
||||
const statusDetails = getStatusDetails(order);
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
data: {
|
||||
order: {
|
||||
id: order.id,
|
||||
orderNumber: order.orderNumber,
|
||||
status: order.status,
|
||||
paymentStatus: order.paymentStatus,
|
||||
totalAmount: parseFloat(order.totalAmount),
|
||||
createdAt: order.createdAt,
|
||||
},
|
||||
tracking: {
|
||||
currentStatus: statusDetails,
|
||||
timeline,
|
||||
deliveryEstimation: deliveryEstimation.data,
|
||||
trackingNumber: order.trackingNumber,
|
||||
},
|
||||
shippingAddress: {
|
||||
name: `${order.address.firstName} ${order.address.lastName}`,
|
||||
addressLine1: order.address.addressLine1,
|
||||
addressLine2: order.address.addressLine2,
|
||||
city: order.address.city,
|
||||
state: order.address.state,
|
||||
postalCode: order.address.postalCode,
|
||||
country: order.address.country,
|
||||
phone: order.address.phone,
|
||||
},
|
||||
items: order.items.map(item => ({
|
||||
productName: item.productName,
|
||||
productSku: item.productSku,
|
||||
quantity: item.quantity,
|
||||
price: parseFloat(item.price),
|
||||
})),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Get order tracking error:', error);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc Update order status (Admin) - FLEXIBLE VERSION
|
||||
* @route PUT /api/admin/orders/:orderId/status
|
||||
* @access Private/Admin
|
||||
*/
|
||||
// exports.updateOrderStatus = async (req, res, next) => {
|
||||
// try {
|
||||
// const { orderId } = req.params;
|
||||
// const { status, trackingNumber, notes, skipValidation = false } = req.body;
|
||||
|
||||
// console.log('📦 Updating order status:', {
|
||||
// orderId,
|
||||
// currentStatus: 'Fetching...',
|
||||
// newStatus: status,
|
||||
// trackingNumber,
|
||||
// });
|
||||
|
||||
// const order = await prisma.order.findUnique({
|
||||
// where: { id: orderId },
|
||||
// });
|
||||
|
||||
// if (!order) {
|
||||
// return res.status(404).json({
|
||||
// success: false,
|
||||
// message: 'Order not found',
|
||||
// });
|
||||
// }
|
||||
|
||||
// console.log('📦 Current order status:', order.status);
|
||||
|
||||
// // ✅ FLEXIBLE VALIDATION - Allow skipping intermediate steps
|
||||
// const validTransitions = {
|
||||
// PENDING: ['CONFIRMED', 'PROCESSING', 'SHIPPED', 'CANCELLED'],
|
||||
// CONFIRMED: ['PROCESSING', 'SHIPPED', 'CANCELLED'],
|
||||
// PROCESSING: ['SHIPPED', 'DELIVERED', 'CANCELLED'],
|
||||
// SHIPPED: ['DELIVERED'],
|
||||
// DELIVERED: ['RETURN_REQUESTED'],
|
||||
// RETURN_REQUESTED: ['REFUNDED'],
|
||||
// CANCELLED: [], // Cannot transition from cancelled
|
||||
// REFUNDED: [], // Cannot transition from refunded
|
||||
// };
|
||||
|
||||
// // Validate transition (unless skipValidation is true)
|
||||
// if (!skipValidation && !validTransitions[order.status]?.includes(status)) {
|
||||
// return res.status(400).json({
|
||||
// success: false,
|
||||
// message: `Cannot transition from ${order.status} to ${status}`,
|
||||
// allowedTransitions: validTransitions[order.status],
|
||||
// hint: 'You can set skipValidation: true to force this transition',
|
||||
// });
|
||||
// }
|
||||
|
||||
// // ✅ Auto-update intermediate statuses if needed
|
||||
// let intermediateUpdates = [];
|
||||
|
||||
// if (order.status === 'PENDING' && status === 'SHIPPED') {
|
||||
// intermediateUpdates = ['CONFIRMED', 'PROCESSING'];
|
||||
// console.log(
|
||||
// '⚡ Auto-updating intermediate statuses:',
|
||||
// intermediateUpdates
|
||||
// );
|
||||
// } else if (order.status === 'CONFIRMED' && status === 'DELIVERED') {
|
||||
// intermediateUpdates = ['PROCESSING', 'SHIPPED'];
|
||||
// console.log(
|
||||
// '⚡ Auto-updating intermediate statuses:',
|
||||
// intermediateUpdates
|
||||
// );
|
||||
// } else if (order.status === 'PENDING' && status === 'DELIVERED') {
|
||||
// intermediateUpdates = ['CONFIRMED', 'PROCESSING', 'SHIPPED'];
|
||||
// console.log(
|
||||
// '⚡ Auto-updating intermediate statuses:',
|
||||
// intermediateUpdates
|
||||
// );
|
||||
// }
|
||||
|
||||
// // Build update data
|
||||
// const updateData = { status };
|
||||
|
||||
// if (trackingNumber) {
|
||||
// updateData.trackingNumber = trackingNumber;
|
||||
// }
|
||||
|
||||
// if (status === 'SHIPPED' && !order.shippedAt) {
|
||||
// updateData.shippedAt = new Date();
|
||||
// }
|
||||
|
||||
// if (status === 'DELIVERED' && !order.deliveredAt) {
|
||||
// updateData.deliveredAt = new Date();
|
||||
// updateData.shippedAt = updateData.shippedAt || new Date(); // Ensure shipped date is set
|
||||
// }
|
||||
|
||||
// // Update order
|
||||
// const updatedOrder = await prisma.order.update({
|
||||
// where: { id: orderId },
|
||||
// data: updateData,
|
||||
// });
|
||||
|
||||
// console.log('✅ Order status updated:', {
|
||||
// from: order.status,
|
||||
// to: updatedOrder.status,
|
||||
// trackingNumber: updatedOrder.trackingNumber,
|
||||
// });
|
||||
|
||||
// // TODO: Send notification to user
|
||||
// // await sendOrderStatusNotification(updatedOrder);
|
||||
|
||||
// res.status(200).json({
|
||||
// success: true,
|
||||
// message: `Order status updated to ${status}`,
|
||||
// data: updatedOrder,
|
||||
// intermediateUpdates:
|
||||
// intermediateUpdates.length > 0 ? intermediateUpdates : undefined,
|
||||
// });
|
||||
// } catch (error) {
|
||||
// console.error('❌ Update order status error:', error);
|
||||
// next(error);
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @desc Update order status (Admin) - ALL MANUAL
|
||||
* @route PUT /api/admin/orders/:orderId/status
|
||||
* @access Private/Admin
|
||||
*/
|
||||
// exports.updateOrderStatus = async (req, res, next) => {
|
||||
// try {
|
||||
// const { orderId } = req.params;
|
||||
// const { status, trackingNumber, notes } = req.body;
|
||||
|
||||
// console.log('📦 Updating order status:', {
|
||||
// orderId,
|
||||
// newStatus: status,
|
||||
// });
|
||||
|
||||
// const order = await prisma.order.findUnique({
|
||||
// where: { id: orderId },
|
||||
// });
|
||||
|
||||
// if (!order) {
|
||||
// return res.status(404).json({
|
||||
// success: false,
|
||||
// message: 'Order not found',
|
||||
// });
|
||||
// }
|
||||
|
||||
// console.log('📦 Current order status:', order.status);
|
||||
|
||||
// // ✅ SIMPLE VALIDATION - Admin can update to any status
|
||||
// const validStatuses = [
|
||||
// 'PENDING',
|
||||
// 'CONFIRMED',
|
||||
// 'PROCESSING',
|
||||
// 'SHIPPED',
|
||||
// 'DELIVERED',
|
||||
// 'CANCELLED',
|
||||
// 'RETURN_REQUESTED',
|
||||
// ];
|
||||
|
||||
// if (!validStatuses.includes(status)) {
|
||||
// return res.status(400).json({
|
||||
// success: false,
|
||||
// message: `Invalid status: ${status}`,
|
||||
// validStatuses,
|
||||
// });
|
||||
// }
|
||||
|
||||
// // Build update data
|
||||
// const updateData = { status };
|
||||
|
||||
// if (trackingNumber) {
|
||||
// updateData.trackingNumber = trackingNumber;
|
||||
// }
|
||||
|
||||
// // Auto-set timestamps
|
||||
// if (status === 'SHIPPED' && !order.shippedAt) {
|
||||
// updateData.shippedAt = new Date();
|
||||
// }
|
||||
|
||||
// if (status === 'DELIVERED' && !order.deliveredAt) {
|
||||
// updateData.deliveredAt = new Date();
|
||||
// }
|
||||
|
||||
// // Update order
|
||||
// const updatedOrder = await prisma.order.update({
|
||||
// where: { id: orderId },
|
||||
// data: updateData,
|
||||
// });
|
||||
|
||||
// console.log('✅ Order status updated:', {
|
||||
// from: order.status,
|
||||
// to: updatedOrder.status,
|
||||
// });
|
||||
|
||||
// res.status(200).json({
|
||||
// success: true,
|
||||
// message: `Order status updated to ${status}`,
|
||||
// data: updatedOrder,
|
||||
// });
|
||||
// } catch (error) {
|
||||
// console.error('❌ Update order status error:', error);
|
||||
// next(error);
|
||||
// }
|
||||
// };
|
||||
|
||||
|
||||
exports.updateOrderStatus = async (req, res, next) => {
|
||||
try {
|
||||
const { orderId } = req.params;
|
||||
const { status, trackingNumber, notes } = req.body;
|
||||
|
||||
const adminId = req.user.id;
|
||||
const ipAddress = req.ip || req.connection.remoteAddress;
|
||||
const userAgent = req.get("user-agent");
|
||||
|
||||
console.log("📦 Updating order status:", {
|
||||
orderId,
|
||||
newStatus: status,
|
||||
admin: adminId,
|
||||
});
|
||||
|
||||
const order = await prisma.order.findUnique({
|
||||
where: { id: orderId },
|
||||
});
|
||||
|
||||
if (!order) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "Order not found",
|
||||
});
|
||||
}
|
||||
|
||||
const oldStatus = order.status;
|
||||
|
||||
const validStatuses = [
|
||||
"PENDING",
|
||||
"CONFIRMED",
|
||||
"PROCESSING",
|
||||
"SHIPPED",
|
||||
"DELIVERED",
|
||||
"CANCELLED",
|
||||
"RETURN_REQUESTED",
|
||||
];
|
||||
|
||||
if (!validStatuses.includes(status)) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: `Invalid status: ${status}`,
|
||||
validStatuses,
|
||||
});
|
||||
}
|
||||
|
||||
const updateData = { status };
|
||||
|
||||
if (trackingNumber) updateData.trackingNumber = trackingNumber;
|
||||
|
||||
if (status === "SHIPPED" && !order.shippedAt) {
|
||||
updateData.shippedAt = new Date();
|
||||
}
|
||||
|
||||
if (status === "DELIVERED" && !order.deliveredAt) {
|
||||
updateData.deliveredAt = new Date();
|
||||
}
|
||||
|
||||
// ✅ SINGLE CLEAN TRANSACTION
|
||||
const result = await prisma.$transaction(async (tx) => {
|
||||
const updatedOrder = await tx.order.update({
|
||||
where: { id: orderId },
|
||||
data: updateData,
|
||||
});
|
||||
|
||||
const historyRecord = await tx.orderStatusHistory.create({
|
||||
data: {
|
||||
orderId,
|
||||
fromStatus: oldStatus,
|
||||
toStatus: status,
|
||||
changedBy: adminId,
|
||||
trackingNumber: trackingNumber || null,
|
||||
notes: notes || null,
|
||||
ipAddress,
|
||||
userAgent,
|
||||
},
|
||||
});
|
||||
|
||||
return { order: updatedOrder, history: historyRecord };
|
||||
});
|
||||
|
||||
// ✅ Auto stock reduction AFTER successful transaction
|
||||
let stockReduction = null;
|
||||
|
||||
if (status === "DELIVERED" && oldStatus !== "DELIVERED") {
|
||||
try {
|
||||
stockReduction = await reduceStockOnDelivery(orderId);
|
||||
console.log("✅ Stock reduced automatically");
|
||||
} catch (err) {
|
||||
console.error("❌ Stock reduction failed:", err);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("✅ Order status updated:", {
|
||||
from: oldStatus,
|
||||
to: result.order.status,
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: `Order status updated from ${oldStatus} to ${status}`,
|
||||
data: result.order,
|
||||
stockReduction,
|
||||
historyId: result.history.id,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("❌ Update order status error:", error);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @desc Get order status history
|
||||
* @route GET /api/admin/orders/:orderId/history
|
||||
* @access Private/Admin
|
||||
*/
|
||||
exports.getOrderStatusHistory = async (req, res, next) => {
|
||||
try {
|
||||
const { orderId } = req.params;
|
||||
|
||||
const history = await prisma.orderStatusHistory.findMany({
|
||||
where: { orderId },
|
||||
include: {
|
||||
admin: {
|
||||
select: {
|
||||
id: true,
|
||||
email: true,
|
||||
firstName: true,
|
||||
lastName: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
data: history,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('❌ Get status history error:', error);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @desc Bulk update order status (Admin)
|
||||
* @route PUT /api/admin/orders/bulk-status
|
||||
* @access Private/Admin
|
||||
*/
|
||||
exports.bulkUpdateOrderStatus = async (req, res, next) => {
|
||||
try {
|
||||
const { orderIds, status, trackingNumbers } = req.body;
|
||||
|
||||
if (!orderIds || !Array.isArray(orderIds) || orderIds.length === 0) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Order IDs array is required',
|
||||
});
|
||||
}
|
||||
|
||||
const updateData = { status };
|
||||
|
||||
if (status === 'SHIPPED') {
|
||||
updateData.shippedAt = new Date();
|
||||
}
|
||||
|
||||
if (status === 'DELIVERED') {
|
||||
updateData.deliveredAt = new Date();
|
||||
}
|
||||
|
||||
// Update all orders
|
||||
const updates = await Promise.all(
|
||||
orderIds.map(async (orderId, index) => {
|
||||
const data = { ...updateData };
|
||||
|
||||
if (trackingNumbers && trackingNumbers[index]) {
|
||||
data.trackingNumber = trackingNumbers[index];
|
||||
}
|
||||
|
||||
return prisma.order.update({
|
||||
where: { id: orderId },
|
||||
data,
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: `${updates.length} orders updated to ${status}`,
|
||||
data: updates,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Bulk update error:', error);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @desc Get delivery estimation for pincode
|
||||
* @route POST /api/delivery/estimate
|
||||
* @access Public
|
||||
*/
|
||||
exports.getDeliveryEstimate = async (req, res, next) => {
|
||||
try {
|
||||
const { pincode, shippingMethod = 'STANDARD' } = req.body;
|
||||
|
||||
if (!pincode) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'Pincode is required',
|
||||
});
|
||||
}
|
||||
|
||||
const estimation = await getDeliveryEstimation(pincode, shippingMethod);
|
||||
|
||||
res.status(200).json(estimation);
|
||||
} catch (error) {
|
||||
console.error('Get delivery estimate error:', error);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
// ==========================================
|
||||
// HELPER FUNCTIONS
|
||||
// ==========================================
|
||||
|
||||
/**
|
||||
* Generate order timeline
|
||||
*/
|
||||
function generateOrderTimeline(order, deliveryEstimation) {
|
||||
const timeline = [];
|
||||
|
||||
timeline.push({
|
||||
status: 'PLACED',
|
||||
title: 'Order Placed',
|
||||
description: 'Your order has been placed successfully',
|
||||
timestamp: order.createdAt,
|
||||
completed: true,
|
||||
icon: '🛒',
|
||||
});
|
||||
|
||||
if (order.status !== 'PENDING') {
|
||||
timeline.push({
|
||||
status: 'CONFIRMED',
|
||||
title: 'Order Confirmed',
|
||||
description: 'Your order has been confirmed',
|
||||
timestamp: order.createdAt,
|
||||
completed: true,
|
||||
icon: '✅',
|
||||
});
|
||||
} else {
|
||||
timeline.push({
|
||||
status: 'CONFIRMED',
|
||||
title: 'Order Confirmation',
|
||||
description: 'Awaiting order confirmation',
|
||||
completed: false,
|
||||
icon: '⏳',
|
||||
});
|
||||
}
|
||||
|
||||
if (['PROCESSING', 'SHIPPED', 'DELIVERED'].includes(order.status)) {
|
||||
timeline.push({
|
||||
status: 'PROCESSING',
|
||||
title: 'Processing',
|
||||
description: 'Your order is being processed',
|
||||
timestamp: order.createdAt,
|
||||
completed: true,
|
||||
icon: '📦',
|
||||
});
|
||||
} else if (order.status === 'CONFIRMED') {
|
||||
timeline.push({
|
||||
status: 'PROCESSING',
|
||||
title: 'Processing',
|
||||
description: 'Order will be processed soon',
|
||||
completed: false,
|
||||
icon: '⏳',
|
||||
});
|
||||
}
|
||||
|
||||
if (['SHIPPED', 'DELIVERED'].includes(order.status)) {
|
||||
timeline.push({
|
||||
status: 'SHIPPED',
|
||||
title: 'Shipped',
|
||||
description: order.trackingNumber
|
||||
? `Tracking: ${order.trackingNumber}`
|
||||
: 'Your order has been shipped',
|
||||
timestamp: order.shippedAt || new Date(),
|
||||
completed: true,
|
||||
icon: '🚚',
|
||||
});
|
||||
} else if (['CONFIRMED', 'PROCESSING'].includes(order.status)) {
|
||||
timeline.push({
|
||||
status: 'SHIPPED',
|
||||
title: 'Shipping',
|
||||
description: 'Your order will be shipped soon',
|
||||
completed: false,
|
||||
icon: '⏳',
|
||||
});
|
||||
}
|
||||
|
||||
if (order.status === 'DELIVERED') {
|
||||
timeline.push({
|
||||
status: 'OUT_FOR_DELIVERY',
|
||||
title: 'Out for Delivery',
|
||||
description: 'Your order is out for delivery',
|
||||
timestamp: order.deliveredAt || new Date(),
|
||||
completed: true,
|
||||
icon: '🛵',
|
||||
});
|
||||
} else if (order.status === 'SHIPPED') {
|
||||
timeline.push({
|
||||
status: 'OUT_FOR_DELIVERY',
|
||||
title: 'Out for Delivery',
|
||||
description: 'Will be out for delivery soon',
|
||||
completed: false,
|
||||
icon: '⏳',
|
||||
});
|
||||
}
|
||||
|
||||
if (order.status === 'DELIVERED') {
|
||||
timeline.push({
|
||||
status: 'DELIVERED',
|
||||
title: 'Delivered',
|
||||
description: 'Your order has been delivered',
|
||||
timestamp: order.deliveredAt,
|
||||
completed: true,
|
||||
icon: '🎉',
|
||||
});
|
||||
} else {
|
||||
const estimatedDate = deliveryEstimation?.estimatedDelivery?.formatted;
|
||||
timeline.push({
|
||||
status: 'DELIVERED',
|
||||
title: 'Delivery',
|
||||
description: estimatedDate
|
||||
? `Expected by ${estimatedDate}`
|
||||
: 'Estimated delivery date will be updated',
|
||||
completed: false,
|
||||
icon: '📍',
|
||||
});
|
||||
}
|
||||
|
||||
return timeline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current status details
|
||||
*/
|
||||
function getStatusDetails(order) {
|
||||
const statusMap = {
|
||||
PENDING: {
|
||||
label: 'Order Pending',
|
||||
description: 'Your order is awaiting confirmation',
|
||||
color: 'yellow',
|
||||
progress: 10,
|
||||
},
|
||||
CONFIRMED: {
|
||||
label: 'Order Confirmed',
|
||||
description: 'Your order has been confirmed and will be processed soon',
|
||||
color: 'blue',
|
||||
progress: 25,
|
||||
},
|
||||
PROCESSING: {
|
||||
label: 'Processing',
|
||||
description: 'Your order is being prepared for shipment',
|
||||
color: 'blue',
|
||||
progress: 50,
|
||||
},
|
||||
SHIPPED: {
|
||||
label: 'Shipped',
|
||||
description: 'Your order is on the way',
|
||||
color: 'purple',
|
||||
progress: 75,
|
||||
},
|
||||
DELIVERED: {
|
||||
label: 'Delivered',
|
||||
description: 'Your order has been delivered',
|
||||
color: 'green',
|
||||
progress: 100,
|
||||
},
|
||||
CANCELLED: {
|
||||
label: 'Cancelled',
|
||||
description: 'Your order has been cancelled',
|
||||
color: 'red',
|
||||
progress: 0,
|
||||
},
|
||||
RETURN_REQUESTED: {
|
||||
label: 'Return Requested',
|
||||
description: 'Return request is being processed',
|
||||
color: 'orange',
|
||||
progress: 100,
|
||||
},
|
||||
REFUNDED: {
|
||||
label: 'Refunded',
|
||||
description: 'Your order has been refunded',
|
||||
color: 'green',
|
||||
progress: 100,
|
||||
},
|
||||
};
|
||||
|
||||
return statusMap[order.status] || statusMap.PENDING;
|
||||
}
|
||||
Reference in New Issue
Block a user