const Product = require('../models/product/Product') const CartItem = require('../models/user/Cart_item') const Order = require('../models/user/Order') const {body, validationResult} = require('express-validator') const dateformat = require('dateformat') const jimp = require('jimp') const fs = require('fs') ////////////////////////////////////////// products controllers module.exports.createProduct = [ [ body('fa_name') .isLength({min: 2}).withMessage('حداقل 2 کاراکتر') .bail() .custom((value, {req}) => { return Product.findOne({'product_details.fa.name': value}) .then(product => { if (product) return Promise.reject('محصول با این نام از قبل وجود دارد.') else return true }) }), body('en_name') .if((value, {req}) => value !== '') .custom((value, {req}) => { return Product.findOne({'product_details.en.name': value}) .then(product => { if (product) return Promise.reject('محصول با این نام از قبل وجود دارد.') else return true }) }), body('de_name') .if((value, {req}) => value !== '') .custom((value, {req}) => { return Product.findOne({'product_details.de.name': value}) .then(product => { if (product) return Promise.reject('محصول با این نام از قبل وجود دارد.') else return true }) }), body('tr_name') .if((value, {req}) => value !== '') .custom((value, {req}) => { return Product.findOne({'product_details.tr.name': value}) .then(product => { if (product) return Promise.reject('محصول با این نام از قبل وجود دارد.') else return true }) }), body('it_name') .if((value, {req}) => value !== '') .custom((value, {req}) => { return Product.findOne({'product_details.it.name': value}) .then(product => { if (product) return Promise.reject('محصول با این نام از قبل وجود دارد.') else return true }) }), body('fa_description') .isLength({min: 2}).withMessage('حداقل 2 کاراکتر'), body('fa_price') .notEmpty().withMessage('قیمت را وارد کنید.') .bail() .isNumeric().withMessage('قیمت باید از جنس عدد باشد'), body('en_price') .notEmpty().withMessage('قیمت را وارد کنید.') .bail() .isNumeric().withMessage('قیمت باید از جنس عدد باشد'), body('de_price') .notEmpty().withMessage('قیمت را وارد کنید.') .bail() .isNumeric().withMessage('قیمت باید از جنس عدد باشد'), body('tr_price') .notEmpty().withMessage('قیمت را وارد کنید.') .bail() .isNumeric().withMessage('قیمت باید از جنس عدد باشد'), body('it_price') .notEmpty().withMessage('قیمت را وارد کنید.') .bail() .isNumeric().withMessage('قیمت باید از جنس عدد باشد'), body('stock') .notEmpty().withMessage('موجودی را وارد کنید.') .bail() .isNumeric().withMessage('موجودی باید از جنس عدد باشد'), body('category') .notEmpty().withMessage('دسته بندی را انتخاب کنید.') ], (req, res) => { const errors = validationResult(req) if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) let image let imageName if (req.files && req.files.image) { image = req.files.image imageName = 'product_' + Date.now() + '.' + image.mimetype.split('/')[1] } else { return res.status(422).json({validation: {image: {msg: 'عکس اجباری است.'}}}) } const data = { price: req.body.price, stock: req.body.stock, category: req.body.category, product_details: { fa: { name: req.body.fa_name, description: req.body.fa_description, price: req.body.fa_price }, en: { name: req.body.en_name, description: req.body.en_description, price: req.body.en_price }, de: { name: req.body.de_name, description: req.body.de_description, price: req.body.de_price }, it: { name: req.body.it_name, description: req.body.it_description, price: req.body.it_price }, tr: { name: req.body.tr_name, description: req.body.tr_description, price: req.body.tr_price } }, created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') } jimp.read(image.data) .then(img => { img .resize(250, jimp.AUTO) .cover(250, 250) .write(`./static/uploads/images/products/${imageName}`) //// write to database data.image = imageName const product = new Product(data) product.save((err, data) => { if (err) console.log(err) return res.json(data) }) }) } ] module.exports.getAllProductsByCategory = [ (req, res) => { Product.find({category: req.params.category}) .select('-product_features -product_images -created_at -updated_at') .exec((err, products) => { if (err) console.log(err) return res.json(products) }) } ] module.exports.getAllProducts = [ (req, res) => { Product.find({}).select('image stock category product_details').exec((err, products) => { if (err) console.log(err) return res.json(products) }) } ] module.exports.getOneProduct = [ async (req, res) => { await Product.findById(req.params.id, async (err, product) => { if (err) return res.status(404).json({message: err}) return res.json(product) }) } ] module.exports.updateProduct = [ [ body('fa_name') .isLength({min: 2}).withMessage('حداقل 2 کاراکتر') .bail() .custom((value, {req}) => { return Product.findOne({'product_details.fa.name': value}) .then(product => { if (product && product._id.toString() !== req.params.id) return Promise.reject('محصول با این نام از قبل وجود دارد.') else return true }) }), body('en_name') .if((value, {req}) => value !== '') .custom((value, {req}) => { return Product.findOne({'product_details.en.name': value}) .then(product => { if (product && product._id.toString() !== req.params.id) return Promise.reject('محصول با این نام از قبل وجود دارد.') else return true }) }), body('de_name') .if((value, {req}) => value !== '') .custom((value, {req}) => { return Product.findOne({'product_details.de.name': value}) .then(product => { if (product && product._id.toString() !== req.params.id) return Promise.reject('محصول با این نام از قبل وجود دارد.') else return true }) }), body('tr_name') .if((value, {req}) => value !== '') .custom((value, {req}) => { return Product.findOne({'product_details.tr.name': value}) .then(product => { if (product && product._id.toString() !== req.params.id) return Promise.reject('محصول با این نام از قبل وجود دارد.') else return true }) }), body('it_name') .if((value, {req}) => value !== '') .custom((value, {req}) => { return Product.findOne({'product_details.it.name': value}) .then(product => { if (product && product._id.toString() !== req.params.id) return Promise.reject('محصول با این نام از قبل وجود دارد.') else return true }) }), body('fa_description') .isLength({min: 2}).withMessage('حداقل 2 کاراکتر'), body('fa_price') .notEmpty().withMessage('قیمت را وارد کنید.') .bail() .isNumeric().withMessage('قیمت باید از جنس عدد باشد'), body('en_price') .notEmpty().withMessage('قیمت را وارد کنید.') .bail() .isNumeric().withMessage('قیمت باید از جنس عدد باشد'), body('de_price') .notEmpty().withMessage('قیمت را وارد کنید.') .bail() .isNumeric().withMessage('قیمت باید از جنس عدد باشد'), body('tr_price') .notEmpty().withMessage('قیمت را وارد کنید.') .bail() .isNumeric().withMessage('قیمت باید از جنس عدد باشد'), body('it_price') .notEmpty().withMessage('قیمت را وارد کنید.') .bail() .isNumeric().withMessage('قیمت باید از جنس عدد باشد'), body('stock') .notEmpty().withMessage('موجودی را وارد کنید.') .bail() .isNumeric().withMessage('موجودی باید از جنس عدد باشد'), body('category') .notEmpty().withMessage('دسته بندی را انتخاب کنید.') ], (req, res) => { const errors = validationResult(req) if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) const data = { price: req.body.price, stock: req.body.stock, category: req.body.category, product_details: { fa: { name: req.body.fa_name, description: req.body.fa_description, price: req.body.fa_price }, en: { name: req.body.en_name, description: req.body.en_description, price: req.body.en_price }, de: { name: req.body.de_name, description: req.body.de_description, price: req.body.de_price }, it: { name: req.body.it_name, description: req.body.it_description, price: req.body.it_price }, tr: { name: req.body.tr_name, description: req.body.tr_description, price: req.body.tr_price } }, updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') } let image let imageName if (req.files && req.files.image) { image = req.files.image imageName = 'product_' + Date.now() + '.' + image.mimetype.split('/')[1] data.image = imageName jimp.read(image.data) .then(img => { img .resize(250, jimp.AUTO) .cover(250, 250) .write(`./static/uploads/images/products/${imageName}`) Product.findByIdAndUpdate(req.params.id, data, (err, oldData) => { if (err) console.log(err) fs.unlink(`./static/${oldData.image}`, (err) => { if (err) console.log(err) }) return res.json({message: 'product updated.'}) }) }) } else { Product.findByIdAndUpdate(req.params.id, data, (err, oldData) => { if (err) console.log(err) return res.json({message: 'product updated.'}) }) } } ] module.exports.deleteProduct = [ (req, res) => { CartItem.findOne({product_id: req.params.id}, (err, item) => { if (err) console.log(err) if (item) { return res.status(401).json({message: 'این محصول درون سبد خرید ثبت شده و نمیتوان آن را حذف کرد.'}) } else { Order.findOne({'order_items.product_id': req.params.id}, (err, order) => { if (err) console.log(err) if (order) { return res.status(401).json({message: 'این محصول درون سفارش ثبت شده و نمیتوان آن را حذف کرد.'}) } else { Product.findByIdAndDelete(req.params.id, (err, product) => { if (err) console.log(err) return res.json({message: 'محصول با موفقیت حذف شد.'}) }) } }) } }) } ] ////////////////////////////////////////// products images controllers module.exports.createProductImage = [ [ body('product_id') .notEmpty().withMessage('مشخصات محصول را وارد کنید.') .bail() .custom((value, {req}) => { return Product.findById(value) .then(product => { return true }) .catch(err => { return Promise.reject('محصولی با این مشخصات وجود ندارد.') }) }) ], (req, res) => { const errors = validationResult(req) if (!errors.isEmpty()) return res.status(422).json({validation: {images: errors.mapped()}}) let image let imageName if (req.files && req.files.image) { image = req.files.image imageName = 'productImages_' + Date.now() + '.' + image.mimetype.split('/')[1] if (image.size / 1024 > 500) return res.status(422).json({validation: {images: {image: {msg: 'حجم عکس نباید بیشتر از 500 کیلوبایت باشد.'}}}}) jimp.read(image.data) .then(img => { img .resize(250, jimp.AUTO) .cover(250, 250) .write(`./static/uploads/images/products/gallery/${imageName}`) //// write to database Product.findById(req.body.product_id, (err, product) => { if (err) console.log(err) product.product_images.push({ image: imageName, created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') }) product.save() return res.json(product) }) }) } else { return res.status(422).json({validation: {images: {image: {msg: 'عکس اجباری است.'}}}}) } } ] module.exports.deleteProductImage = [ (req, res) => { Product.findOne({'product_images._id': req.params.imageID}, (err, product) => { if (err) return res.status(404).json(err) const productImage = product.product_images.id(req.params.imageID) fs.unlink(`./static/${productImage.image}`, err => { if (err) console.log(err) }) productImage.remove() product.save(err => { if (err) console.log(err) }) return res.json(product) }) } ] ////////////////////////////////////////// products features controllers module.exports.createProductFeature = [ [ body('fa_name') .notEmpty().withMessage('عنوان نباید خالی باشد'), body('en_name') .notEmpty().withMessage('عنوان نباید خالی باشد'), body('de_name') .notEmpty().withMessage('عنوان نباید خالی باشد'), body('tr_name') .notEmpty().withMessage('عنوان نباید خالی باشد'), body('it_name') .notEmpty().withMessage('عنوان نباید خالی باشد'), body('fa_value') .notEmpty().withMessage('توضیحات نباید خالی باشد'), body('en_value') .notEmpty().withMessage('توضیحات نباید خالی باشد'), body('tr_value') .notEmpty().withMessage('توضیحات نباید خالی باشد'), body('de_value') .notEmpty().withMessage('توضیحات نباید خالی باشد'), body('it_value') .notEmpty().withMessage('توضیحات نباید خالی باشد'), body('product_id') .notEmpty().withMessage('مشخصات محصول را وارد کنید.') .bail() .custom((value, {req}) => { return Product.findById(value) .then(product => { return true }) .catch(err => { return Promise.reject('محصولی با این مشخصات وجود ندارد.') }) }) ], (req, res) => { const errors = validationResult(req) if (!errors.isEmpty()) return res.status(422).json({validation: {features: errors.mapped()}}) const data = { fa: { name: req.body.fa_name, value: req.body.fa_value }, en: { name: req.body.en_name, value: req.body.en_value }, de: { name: req.body.de_name, value: req.body.de_value }, tr: { name: req.body.tr_name, value: req.body.tr_value }, it: { name: req.body.it_name, value: req.body.it_value }, created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') } Product.findById(req.body.product_id, (err, product) => { if (err) console.log(err) product.product_features.push(data) product.save() return res.json(product) }) } ] module.exports.deleteProductFeature = [ (req, res) => { Product.findOne({'product_features._id': req.params.featureID}, (err, product) => { if (err) return res.status(500).json({message: err}) product.product_features.id(req.params.featureID).remove() product.save() return res.json(product) }) } ]