Spaces:
Running
Running
feat: implement core backend POS API with authentication, role-based access control, menu management, and order processing logic.
1e480b5 Download src/controllers/menuController.js from aliroohan179/face: direct link, hf CLI and curl.
- Browser
- Download file 3.88 kB
-
https://huggingface.co/spaces/aliroohan179/face/resolve/main/src/controllers/menuController.js
- Command line
-
hf download hf://spaces/aliroohan179/face/src/controllers/menuController.js
-
curl -L -o menuController.js https://huggingface.co/spaces/aliroohan179/face/resolve/main/src/controllers/menuController.js
3.88 kB
| const Category = require('../models/Category'); | |
| const MenuItem = require('../models/MenuItem'); | |
| const { uploadMenuImage } = require('../config/cloudinary'); | |
| // GET /api/menu/all β returns categories + their items (used for offline cache seeding) | |
| exports.getAll = async (req, res) => { | |
| const [categories, items] = await Promise.all([ | |
| Category.find({ hidden: false }).sort({ order: 1, name: 1 }), | |
| MenuItem.find().populate('category', 'name order').sort({ name: 1 }), | |
| ]); | |
| res.json({ categories, items }); | |
| }; | |
| // ββ Categories ββββββββββββββββββββββββββββββββββββββββββββββ | |
| exports.getCategories = async (req, res) => { | |
| const cats = await Category.find().sort({ order: 1, name: 1 }); | |
| res.json(cats); | |
| }; | |
| exports.createCategory = async (req, res) => { | |
| const { name, order, hidden } = req.body; | |
| const cat = await Category.create({ name, order: order ?? 0, hidden: hidden ?? false }); | |
| res.status(201).json(cat); | |
| }; | |
| exports.updateCategory = async (req, res) => { | |
| const cat = await Category.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true }); | |
| if (!cat) return res.status(404).json({ message: 'Category not found' }); | |
| res.json(cat); | |
| }; | |
| exports.deleteCategory = async (req, res) => { | |
| const count = await MenuItem.countDocuments({ category: req.params.id }); | |
| if (count > 0) return res.status(400).json({ message: `Cannot delete: ${count} menu item(s) use this category` }); | |
| await Category.findByIdAndDelete(req.params.id); | |
| res.json({ message: 'Category deleted' }); | |
| }; | |
| // ββ Menu Items βββββββββββββββββββββββββββββββββββββββββββββββ | |
| exports.createItem = async (req, res) => { | |
| const { name, category, variants, available } = req.body; | |
| const parsedVariants = typeof variants === 'string' ? JSON.parse(variants) : variants; | |
| const image = req.file ? req.file.path : null; // Cloudinary URL | |
| const item = await MenuItem.create({ name, category, variants: parsedVariants, available: available ?? true, image }); | |
| await item.populate('category', 'name order'); | |
| res.status(201).json(item); | |
| }; | |
| exports.updateItem = async (req, res) => { | |
| const { variants, ...rest } = req.body; | |
| const update = { ...rest }; | |
| if (variants) update.variants = typeof variants === 'string' ? JSON.parse(variants) : variants; | |
| if (req.file) update.image = req.file.path; | |
| const item = await MenuItem.findByIdAndUpdate(req.params.id, update, { new: true, runValidators: true }).populate('category', 'name order'); | |
| if (!item) return res.status(404).json({ message: 'Item not found' }); | |
| res.json(item); | |
| }; | |
| exports.deleteItem = async (req, res) => { | |
| const item = await MenuItem.findByIdAndDelete(req.params.id); | |
| if (!item) return res.status(404).json({ message: 'Item not found' }); | |
| res.json({ message: 'Item deleted' }); | |
| }; | |
| exports.toggleAvailability = async (req, res) => { | |
| const { available, variantId } = req.body; | |
| const item = await MenuItem.findById(req.params.id); | |
| if (!item) return res.status(404).json({ message: 'Item not found' }); | |
| if (variantId) { | |
| // Toggle a specific variant | |
| const variant = item.variants.id(variantId); | |
| if (!variant) return res.status(404).json({ message: 'Variant not found' }); | |
| variant.available = available ?? !variant.available; | |
| } else { | |
| // Toggle the whole item | |
| item.available = available ?? !item.available; | |
| } | |
| await item.save(); | |
| res.json(item); | |
| }; | |
| // POST /api/menu/upload-image β standalone image upload (returns URL for use in create/update) | |
| exports.uploadImage = [ | |
| uploadMenuImage.single('image'), | |
| (req, res) => { | |
| if (!req.file) return res.status(400).json({ message: 'No image uploaded' }); | |
| res.json({ url: req.file.path }); | |
| }, | |
| ]; | |