- Products store packing-slip title aliases; matcher checks exact title/alias first so previously-matched items skip fuzzy matching entirely - Packing-slip imports snapshot printingCost/costOfGoods/productId onto order items; profit analysis reads stored costs so catalog edits don't rewrite history - Etsy statement fees allocate to orders via Order # references in Title/Info instead of date proximity; shop-level fees (listings, ads) no longer leak into order fees - Remove broken transaction-fee exclusion guard (order totals are gross, so all expenses count once) - Remove debug buttons, date-fix banner, test files, and console.log noise; Clear All Orders now uses a bulk DELETE /orders endpoint Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
117 lines
3.7 KiB
TypeScript
117 lines
3.7 KiB
TypeScript
import { Router, Response } from 'express';
|
|
import Order from '../models/Order';
|
|
import Customer from '../models/Customer';
|
|
import { AuthRequest } from '../middleware/authenticate';
|
|
|
|
const router = Router();
|
|
|
|
router.get('/', async (req: AuthRequest, res: Response) => {
|
|
try {
|
|
const { page = 1, limit = 200, status, paymentStatus } = req.query;
|
|
const filter: any = { userId: req.userId };
|
|
if (status) filter.status = status;
|
|
if (paymentStatus) filter.paymentStatus = paymentStatus;
|
|
|
|
const orders = await Order.find(filter)
|
|
.sort({ dateOrdered: -1 })
|
|
.limit(Number(limit))
|
|
.skip((Number(page) - 1) * Number(limit));
|
|
const total = await Order.countDocuments(filter);
|
|
|
|
res.json({ orders, total, page: Number(page), limit: Number(limit) });
|
|
} catch (err) {
|
|
res.status(500).json({ message: 'Failed to fetch orders', error: err });
|
|
}
|
|
});
|
|
|
|
router.post('/', async (req: AuthRequest, res: Response) => {
|
|
try {
|
|
const { _id, ...body } = req.body;
|
|
const order = new Order({ ...body, userId: req.userId });
|
|
await order.save();
|
|
|
|
if (order.customerId) {
|
|
await Customer.findOneAndUpdate(
|
|
{ _id: order.customerId, userId: req.userId },
|
|
{ $inc: { totalOrders: 1, totalSpent: order.total } }
|
|
);
|
|
}
|
|
|
|
res.status(201).json(order);
|
|
} catch (err) {
|
|
res.status(400).json({ message: 'Failed to create order', error: err });
|
|
}
|
|
});
|
|
|
|
router.post('/bulk', async (req: AuthRequest, res: Response) => {
|
|
try {
|
|
const orders: any[] = req.body;
|
|
const results = { created: 0, updated: 0, errors: 0 };
|
|
|
|
for (const orderData of orders) {
|
|
try {
|
|
const { _id, ...body } = orderData;
|
|
const existing = await Order.findOne({ orderNumber: body.orderNumber, userId: req.userId });
|
|
if (existing) {
|
|
await Order.findByIdAndUpdate(existing._id, { ...body, userId: req.userId }, { new: true, runValidators: true });
|
|
results.updated++;
|
|
} else {
|
|
await Order.create({ ...body, userId: req.userId });
|
|
results.created++;
|
|
}
|
|
} catch {
|
|
results.errors++;
|
|
}
|
|
}
|
|
|
|
res.json(results);
|
|
} catch (err) {
|
|
res.status(400).json({ message: 'Failed to bulk import orders', error: err });
|
|
}
|
|
});
|
|
|
|
router.get('/:id', async (req: AuthRequest, res: Response) => {
|
|
try {
|
|
const order = await Order.findOne({ _id: req.params.id, userId: req.userId });
|
|
if (!order) return res.status(404).json({ message: 'Order not found' });
|
|
res.json(order);
|
|
} catch (err) {
|
|
res.status(500).json({ message: 'Failed to fetch order', error: err });
|
|
}
|
|
});
|
|
|
|
router.put('/:id', async (req: AuthRequest, res: Response) => {
|
|
try {
|
|
const { _id, ...body } = req.body;
|
|
const order = await Order.findOneAndUpdate(
|
|
{ _id: req.params.id, userId: req.userId },
|
|
body,
|
|
{ new: true, runValidators: true }
|
|
);
|
|
if (!order) return res.status(404).json({ message: 'Order not found' });
|
|
res.json(order);
|
|
} catch (err) {
|
|
res.status(400).json({ message: 'Failed to update order', error: err });
|
|
}
|
|
});
|
|
|
|
router.delete('/', async (req: AuthRequest, res: Response) => {
|
|
try {
|
|
const result = await Order.deleteMany({ userId: req.userId });
|
|
res.json({ message: 'All orders deleted', deleted: result.deletedCount });
|
|
} catch (err) {
|
|
res.status(500).json({ message: 'Failed to delete orders', error: err });
|
|
}
|
|
});
|
|
|
|
router.delete('/:id', async (req: AuthRequest, res: Response) => {
|
|
try {
|
|
const order = await Order.findOneAndDelete({ _id: req.params.id, userId: req.userId });
|
|
if (!order) return res.status(404).json({ message: 'Order not found' });
|
|
res.json({ message: 'Order deleted' });
|
|
} catch (err) {
|
|
res.status(500).json({ message: 'Failed to delete order', error: err });
|
|
}
|
|
});
|
|
|
|
export default router;
|