const Product = require('../models/product/Product') const {body, validationResult} = require('express-validator') const dateformat = require('dateformat') const jimp = require('jimp') const fs = require('fs') const v_m = require('../validation_messages') // local variables const shortDescriptionLength = 150 const coverWidth = 1010 const coverHeight = 534 const coverQuality = 100 const thumbWidth = 360 const thumbHeight = 294 const thumbQuality = 70 const moreSectionWidth = 778 const moreSectionHeight = 395 const moreSectionQuality = 70 const renderImageWidth = 300 const renderImageHeight = 300 const renderImageQuality = 70 const chartImageQuality = 100 ////////////////////////////////////////// products controllers module.exports.createProduct = [ [ body('fa_name') .notEmpty().withMessage(v_m['fa'].required.title) .bail() .custom((value, {req}) => { return Product.findOne({'product_details.fa.name': value}) .then(product => { if (product) return Promise.reject(v_m['fa'].duplicated.name) else return true }) }), body('en_name') .notEmpty().withMessage(v_m['fa'].required.title) .bail() .custom((value, {req}) => { return Product.findOne({'product_details.en.name': value}) .then(product => { if (product) return Promise.reject(v_m['fa'].duplicated.name) else return true }) }), body('fa_short_description') .notEmpty().withMessage(v_m['fa'].required.caption), body('en_short_description') .notEmpty().withMessage(v_m['fa'].required.caption), body('fa_page_title') .notEmpty().withMessage(v_m['fa'].required.title), body('en_page_title') .notEmpty().withMessage(v_m['fa'].required.title), body('fa_page_description') .notEmpty().withMessage(v_m['fa'].required.caption), body('en_page_description') .notEmpty().withMessage(v_m['fa'].required.caption), body('en_page_description') .notEmpty().withMessage(v_m['fa'].required.caption), body('category') .notEmpty().withMessage(v_m['fa'].required.category) ], async (req, res) => { const errors = validationResult(req) if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) if (!req.files || !req.files.cover) return res.status(422).json({validation: {cover: {msg: v_m['fa'].required.cover}}}) let cover = 'product_' + Date.now() + '.' + req.files.cover.mimetype.split('/')[1] let thumb = 'thumb_' + cover let more_section_image1 = null let more_section_image2 = null let render_image1 = null let render_image2 = null let chart_image = null //// generate files names if (req.files) { if (req.files.more_section_image1) { more_section_image1 = 'product_' + Date.now() + 1 + '.' + req.files.more_section_image1.mimetype.split('/')[1] } if (req.files.more_section_image2) { more_section_image2 = 'product_' + Date.now() + 2 + '.' + req.files.more_section_image2.mimetype.split('/')[1] } if (req.files.render_image1) { render_image1 = 'product_' + Date.now() + 3 + '.' + req.files.render_image1.mimetype.split('/')[1] } if (req.files.render_image2) { render_image2 = 'product_' + Date.now() + 4 + '.' + req.files.render_image2.mimetype.split('/')[1] } if (req.files.chart_image) { chart_image = 'product_' + Date.now() + 5 + '.' + req.files.chart_image.mimetype.split('/')[1] } } const data = { cover: cover, thumb: thumb, category: req.body.category, more_section: req.body.more_section, download_section: req.body.download_section, favorite: req.body.favorite, product_details: { fa: { name: req.body.fa_name, short_description: req.body.fa_short_description.slice(0, shortDescriptionLength) + ' ... ', page_title: req.body.fa_page_title, page_description: req.body.fa_page_description, more_title1: req.body.fa_more_title1, more_description1: req.body.fa_more_description1, more_title2: req.body.fa_more_title2, more_description2: req.body.fa_more_description2, render_caption1: req.body.fa_render_caption1, render_caption2: req.body.fa_render_caption2, chart_title: req.body.fa_chart_title, chart_description: req.body.fa_chart_description }, en: { name: req.body.en_name, short_description: req.body.en_short_description.slice(0, shortDescriptionLength) + ' ... ', page_title: req.body.en_page_title, page_description: req.body.en_page_description, more_title1: req.body.en_more_title1, more_description1: req.body.en_more_description1, more_title2: req.body.en_more_title2, more_description2: req.body.en_more_description2, render_caption1: req.body.en_render_caption1, render_caption2: req.body.en_render_caption2, chart_title: req.body.en_chart_title, chart_description: req.body.en_chart_description } }, created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') } if (req.files.more_section_image1) data.more_section_image1 = more_section_image1 if (req.files.more_section_image2) data.more_section_image2 = more_section_image2 if (req.files.render_image1) data.render_image1 = render_image1 if (req.files.render_image2) data.render_image2 = render_image2 if (req.files.chart_image) data.chart_image = chart_image //// save images if (req.files) { if (req.files.cover) { await jimp.read(req.files.cover.data) .then(img => { img .cover(coverWidth, coverHeight) .quality(coverQuality) .write(`./static/uploads/images/products/${cover}`) .resize(thumbWidth, jimp.AUTO) .cover(thumbWidth, thumbHeight) .quality(thumbQuality) .write(`./static/uploads/images/products/${thumb}`) }) } if (req.files.more_section_image1) { await jimp.read(req.files.more_section_image1.data) .then(img => { img .resize(moreSectionWidth, jimp.AUTO) .cover(moreSectionWidth, moreSectionHeight) .quality(moreSectionQuality) .write(`./static/uploads/images/products/${more_section_image1}`) }) } if (req.files.more_section_image2) { await jimp.read(req.files.more_section_image2.data) .then(img => { img .resize(moreSectionWidth, jimp.AUTO) .cover(moreSectionWidth, moreSectionHeight) .quality(moreSectionQuality) .write(`./static/uploads/images/products/${more_section_image2}`) }) } if (req.files.render_image1) { await jimp.read(req.files.render_image1.data) .then(img => { img .resize(renderImageWidth, jimp.AUTO) .cover(renderImageWidth, renderImageHeight) .quality(renderImageQuality) .write(`./static/uploads/images/products/${render_image1}`) }) } if (req.files.render_image2) { await jimp.read(req.files.render_image2.data) .then(img => { img .resize(renderImageWidth, jimp.AUTO) .cover(renderImageWidth, renderImageHeight) .quality(renderImageQuality) .write(`./static/uploads/images/products/${render_image2}`) }) } if (req.files.chart_image) { await jimp.read(req.files.chart_image.data) .then(img => { img .quality(chartImageQuality) .write(`./static/uploads/images/products/${chart_image}`) }) } } //// write to database const product = new Product(data) product.save((err, data) => { if (err) console.log(err) return res.json(data) }) } ] module.exports.getFavoriteProducts = [ (req, res) => { Product.find({favorite: true}) .select('thumb category product_details') .exec((err, products) => { if (err) console.log(err) return res.json(products) }) } ] module.exports.getAllProducts = [ (req, res) => { Product.find({}).select('thumb category product_details favorite').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') .notEmpty().withMessage(v_m['fa'].required.title) .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(v_m['fa'].duplicated.name) else return true }) }), body('en_name') .notEmpty().withMessage(v_m['fa'].required.title) .bail() .custom((value, {req}) => { return Product.findOne({'product_details.en.name': value}) .then(product => { if (product && product._id.toString() !== req.params.id) return Promise.reject(v_m['fa'].duplicated.name) else return true }) }), body('fa_short_description') .notEmpty().withMessage(v_m['fa'].required.caption), body('en_short_description') .notEmpty().withMessage(v_m['fa'].required.caption), body('fa_page_title') .notEmpty().withMessage(v_m['fa'].required.title), body('en_page_title') .notEmpty().withMessage(v_m['fa'].required.title), body('fa_page_description') .notEmpty().withMessage(v_m['fa'].required.caption), body('en_page_description') .notEmpty().withMessage(v_m['fa'].required.caption), body('en_page_description') .notEmpty().withMessage(v_m['fa'].required.caption), body('category') .notEmpty().withMessage(v_m['fa'].required.category) ], async (req, res) => { const errors = validationResult(req) if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) let cover = null let more_section_image1 = null let more_section_image2 = null let render_image1 = null let render_image2 = null let chart_image = null //// generate files names if (req.files) { if (req.files.cover) { cover = 'product_' + Date.now() + '.' + req.files.cover.mimetype.split('/')[1] thumb = 'thumb_' + cover } if (req.files.more_section_image1) { more_section_image1 = 'product_' + Date.now() + 1 + '.' + req.files.more_section_image1.mimetype.split('/')[1] } if (req.files.more_section_image2) { more_section_image2 = 'product_' + Date.now() + 2 + '.' + req.files.more_section_image2.mimetype.split('/')[1] } if (req.files.render_image1) { render_image1 = 'product_' + Date.now() + 3 + '.' + req.files.render_image1.mimetype.split('/')[1] } if (req.files.render_image2) { render_image2 = 'product_' + Date.now() + 4 + '.' + req.files.render_image2.mimetype.split('/')[1] } if (req.files.chart_image) { chart_image = 'product_' + Date.now() + 5 + '.' + req.files.chart_image.mimetype.split('/')[1] } } const data = { category: req.body.category, more_section: req.body.more_section, download_section: req.body.download_section, favorite: req.body.favorite, product_details: { fa: { name: req.body.fa_name, short_description: req.body.fa_short_description.slice(0, shortDescriptionLength) + ' ... ', page_title: req.body.fa_page_title, page_description: req.body.fa_page_description, more_title1: req.body.fa_more_title1, more_description1: req.body.fa_more_description1, more_title2: req.body.fa_more_title2, more_description2: req.body.fa_more_description2, render_caption1: req.body.fa_render_caption1, render_caption2: req.body.fa_render_caption2, chart_title: req.body.fa_chart_title, chart_description: req.body.fa_chart_description }, en: { name: req.body.en_name, short_description: req.body.en_short_description.slice(0, shortDescriptionLength) + ' ... ', page_title: req.body.en_page_title, page_description: req.body.en_page_description, more_title1: req.body.en_more_title1, more_description1: req.body.en_more_description1, more_title2: req.body.en_more_title2, more_description2: req.body.en_more_description2, render_caption1: req.body.en_render_caption1, render_caption2: req.body.en_render_caption2, chart_title: req.body.en_chart_title, chart_description: req.body.en_chart_description } }, updated_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') } //// save images if (req.files) { if (req.files.cover) { data.cover = cover data.thumb = thumb await jimp.read(req.files.cover.data) .then(img => { img .cover(coverWidth, coverHeight) .quality(coverQuality) .write(`./static/uploads/images/products/${cover}`) .resize(thumbWidth, jimp.AUTO) .cover(thumbWidth, thumbHeight) .quality(thumbQuality) .write(`./static/uploads/images/products/${thumb}`) }) } if (req.files.more_section_image1) { data.more_section_image1 = more_section_image1 await jimp.read(req.files.more_section_image1.data) .then(img => { img .resize(moreSectionWidth, jimp.AUTO) .cover(moreSectionWidth, moreSectionHeight) .quality(moreSectionQuality) .write(`./static/uploads/images/products/${more_section_image1}`) }) } if (req.files.more_section_image2) { data.more_section_image2 = more_section_image2 await jimp.read(req.files.more_section_image2.data) .then(img => { img .resize(moreSectionWidth, jimp.AUTO) .cover(moreSectionWidth, moreSectionHeight) .quality(moreSectionQuality) .write(`./static/uploads/images/products/${more_section_image2}`) }) } if (req.files.render_image1) { data.render_image1 = render_image1 await jimp.read(req.files.render_image1.data) .then(img => { img .resize(renderImageWidth, jimp.AUTO) .cover(renderImageWidth, renderImageHeight) .quality(renderImageQuality) .write(`./static/uploads/images/products/${render_image1}`) }) } if (req.files.render_image2) { data.render_image2 = render_image2 await jimp.read(req.files.render_image2.data) .then(img => { img .resize(renderImageWidth, jimp.AUTO) .cover(renderImageWidth, renderImageHeight) .quality(renderImageQuality) .write(`./static/uploads/images/products/${render_image2}`) }) } if (req.files.chart_image) { data.chart_image = chart_image await jimp.read(req.files.chart_image.data) .then(img => { img .quality(chartImageQuality) .write(`./static/uploads/images/products/${chart_image}`) }) } } //// write to database Product.findByIdAndUpdate(req.params.id, data, (err, oldData) => { if (err) console.log(err) if (req.files) { if (req.files.cover) { fs.unlink(`./static/${oldData.cover}`, err => { if (err) console.log(err) }) fs.unlink(`./static/${oldData.thumb}`, err => { if (err) console.log(err) }) } if (req.files.more_section_image1 && oldData.more_section_image1) fs.unlink(`./static/${oldData.more_section_image1}`, err => { if (err) console.log(err) }) if (req.files.more_section_image2 && oldData.more_section_image2) fs.unlink(`./static/${oldData.more_section_image2}`, err => { if (err) console.log(err) }) if (req.files.render_image1 && oldData.render_image1) fs.unlink(`./static/${oldData.render_image1}`, err => { if (err) console.log(err) }) if (req.files.render_image2 && oldData.render_image2) fs.unlink(`./static/${oldData.render_image2}`, err => { if (err) console.log(err) }) if (req.files.chart_image && oldData.chart_image) fs.unlink(`./static/${oldData.chart_image}`, err => { if (err) console.log(err) }) } Product.findById(oldData._id, (err, data) => { if (err) console.log(err) return res.json(data) }) }) } ] module.exports.deleteProduct = [ (req, res) => { Product.findByIdAndDelete(req.params.id, (err, product) => { if (err) console.log(err) fs.unlink(`./static/${product.cover}`, err => { if (err) console.log(err) }) fs.unlink(`./static/${product.thumb}`, err => { if (err) console.log(err) }) if (product.more_section_image1) fs.unlink(`./static/${product.more_section_image1}`, err => { if (err) console.log(err) }) if (product.more_section_image2) fs.unlink(`./static/${product.more_section_image2}`, err => { if (err) console.log(err) }) if (product.render_image1) fs.unlink(`./static/${product.render_image1}`, err => { if (err) console.log(err) }) if (product.render_image2) fs.unlink(`./static/${product.render_image2}`, err => { if (err) console.log(err) }) if (product.chart_image) fs.unlink(`./static/${product.chart_image}`, err => { if (err) console.log(err) }) if (product.images.length) { product.images.forEach(item => { fs.unlink(`./static/${item.image}`, err => { if (err) console.log(err) }) }) } if (product.pdf_files.length) { product.pdf_files.forEach(item => { fs.unlink(`./static/${item.file.fa}`, err => { if (err) console.log(err) }) fs.unlink(`./static/${item.file.en}`, err => { if (err) console.log(err) }) }) } return res.json({message: v_m['fa'].response.success_remove}) }) } ] ////////////////////////////////////////// products images controllers module.exports.createProductImage = [ [ body('product_id') .custom((value, {req}) => { return Product.findById(value) .then(product => { return true }) .catch(err => { return Promise.reject(v_m['fa'].not_found.item_id) }) }) ], (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] jimp.read(image.data) .then(img => { img .cover(coverWidth, coverHeight) .quality(coverQuality) .write(`./static/uploads/images/products/${imageName}`) //// write to database Product.findById(req.body.product_id, (err, product) => { if (err) console.log(err) 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: v_m['fa'].required.image}}}}) } } ] module.exports.deleteProductImage = [ (req, res) => { Product.findOne({'images._id': req.params.imageID}, (err, product) => { if (err) return res.status(404).json(err) const productImage = 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.createPDF = [ [ body('fa_pdf') .notEmpty().withMessage(v_m['fa'].required.title), body('en_pdf') .notEmpty().withMessage(v_m['fa'].required.title), body('product_id') .custom((value, {req}) => { return Product.findById(value) .then(product => { return true }) .catch(err => { return Promise.reject(v_m['fa'].not_found.item_id) }) }) ], (req, res) => { const errors = validationResult(req) if (!errors.isEmpty()) return res.status(422).json({validation: errors.mapped()}) if (!req.files || !req.files.file_fa) return res.status(422).json({validation: {file_fa: {msg: v_m['fa'].required.file}}}) if (!req.files || !req.files.file_en) return res.status(422).json({validation: {file_en: {msg: v_m['fa'].required.file}}}) Product.findById(req.body.product_id, (err, product) => { if (err) console.log(err) let fileFa = 'fa_' + product.product_details.fa.name + Date.now() + '.' + req.files.file_fa.mimetype.split('/')[1] let fileEn = 'en_' + product.product_details.en.name + Date.now() + '.' + req.files.file_en.mimetype.split('/')[1] req.files.file_fa.mv(`./static/uploads/pdf/${fileFa}`, err => { if (err) console.log(err) }) req.files.file_en.mv(`./static/uploads/pdf/${fileEn}`, err => { if (err) console.log(err) }) const data = { file: { fa: fileFa, en: fileEn }, pdf_details: { fa: { name: req.body.fa_pdf }, en: { name: req.body.en_pdf } }, created_at: dateformat(Date.now(), 'yyyy-mm-dd HH:MM:ss') } product.pdf_files.push(data) product.save() return res.json(product) }) } ] module.exports.deletePDF = [ (req, res) => { Product.findOne({'pdf_files._id': req.params.pdfID}, (err, product) => { if (err) return res.status(500).json({message: err}) let pdf = product.pdf_files.id(req.params.pdfID) pdf.remove(cb => { fs.unlink(`./static/${pdf.file.fa}`, err => { if (err) console.log(err) }) fs.unlink(`./static/${pdf.file.en}`, err => { if (err) console.log(err) }) }) product.save() return res.json(product) }) } ]