536 lines
18 KiB
JavaScript
536 lines
18 KiB
JavaScript
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)
|
|
})
|
|
}
|
|
]
|