const VendorRequest = require('../models/vendorRequestModel'); const Provider = require('../models/providerModel'); const User = require('../models/userModel'); const { sendVendorAcceptanceEmail, sendVendorRejectionEmail, } = require('../utils/emailService'); const { deleteImage, getPublicIdFromUrl } = require('../config/cloudinary'); // 1. Submit Vendor Request (Public) exports.submitRequest = async (req, res) => { try { const requestData = { ...req.body }; if (req.file) { requestData.logo = req.file.path; } const newRequest = await VendorRequest.create(requestData); res.status(201).json({ status: 'success', message: 'Form submitted successfully', data: { request: newRequest }, }); } catch (err) { res.status(400).json({ status: 'fail', message: err.message, }); } }; // 2. Get All Requests (Admin) exports.getAllRequests = async (req, res) => { try { const requests = await VendorRequest.find().sort({ createdAt: -1 }); res.status(200).json({ status: 'success', results: requests.length, data: { requests }, }); } catch (err) { res.status(500).json({ status: 'fail', message: err.message, }); } }; // 3. Get Single Request (Admin) exports.getRequest = async (req, res) => { try { const request = await VendorRequest.findById(req.params.id); if (!request) { return res.status(404).json({ status: 'fail', message: 'No request found with that ID', }); } res.status(200).json({ status: 'success', data: { request }, }); } catch (err) { res.status(400).json({ status: 'fail', message: err.message, }); } }; // 4. Delete Request (Admin) exports.deleteRequest = async (req, res) => { try { const request = await VendorRequest.findById(req.params.id); if (!request) { return res.status(404).json({ status: 'fail', message: 'No request found with that ID', }); } // Delete logo from Cloudinary if it exists if (request.logo) { const publicId = getPublicIdFromUrl(request.logo); if (publicId) await deleteImage(publicId).catch(() => {}); } await VendorRequest.findByIdAndDelete(req.params.id); res.status(204).json({ status: 'success', data: null, }); } catch (err) { res.status(400).json({ status: 'fail', message: err.message, }); } }; // 5. Respond to Request (Admin) // This will handle both Accept and Refuse exports.respondToRequest = async (req, res) => { try { const { status, password } = req.body; const request = await VendorRequest.findById(req.params.id); if (!request) { return res.status(404).json({ status: 'fail', message: 'No request found with that ID', }); } if (status === 'accepted') { // Create Provider Account (Logic similar to AdminProviderAdd.jsx handles it on frontend, but we need backend logic too) // Actually, the user said: "if i accept it uses the info in the form and give me option to assign his password" // So the admin will submit a final form with password. // First check if user with same email or phone exists const existingUser = await User.findOne({ $or: [{ email: request.email }, { phone: request.phoneNumber }], }); if (existingUser) { const field = existingUser.email === request.email ? 'البريد الإلكتروني' : 'رقم الهاتف'; return res.status(400).json({ status: 'fail', message: `${field} مسجل بالفعل لمستخدم آخر`, }); } // Get last provider ID for auto-increment const lastProvider = await Provider.findOne().sort({ id: -1 }); const autoId = lastProvider ? lastProvider.id + 1 : 1; // 1. Create Provider document (without user link yet) const newProvider = await Provider.create({ id: autoId, name: request.ownerName, storeName: request.businessName, phoneNumber: request.phoneNumber, address: request.address, logo: request.logo, }); // 2. Create User account for vendor and link to provider try { const newUser = await User.create({ name: request.ownerName, email: request.email, phone: request.phoneNumber, password: password, role: 'vendor', provider: newProvider._id, }); // 3. Update provider with user reference newProvider.user = newUser._id; await newProvider.save(); // 4. Update Request Status request.status = 'accepted'; request.reviewedAt = Date.now(); await request.save(); // 5. Send Acceptance Email await sendVendorAcceptanceEmail({ email: request.email, name: request.ownerName, storeName: request.businessName, password: password, }); return res.status(200).json({ status: 'success', message: 'Request accepted and provider created', data: { provider: newProvider }, }); } catch (err) { // Rollback: Delete the created provider if user creation fails await Provider.findByIdAndDelete(newProvider._id); throw err; } } else if (status === 'rejected') { request.status = 'rejected'; request.reviewedAt = Date.now(); await request.save(); // Send Rejection Email await sendVendorRejectionEmail({ email: request.email, name: request.ownerName, storeName: request.businessName, }); return res.status(200).json({ status: 'success', message: 'Request rejected', }); } } catch (err) { res.status(400).json({ status: 'fail', message: err.message, }); } };