diff --git a/app.js b/app.js index e018f5e..6675cb8 100644 --- a/app.js +++ b/app.js @@ -3,12 +3,16 @@ var express = require('express'); var path = require('path'); var cookieParser = require('cookie-parser'); var logger = require('morgan'); +// const { default: mongoose } = require('mongoose'); + var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users'); var productRouter = require('./routes/product/router'); var categoryRouter = require('./routes/category/router'); -var suppliersRouter = require('./routes/suppliers'); +var suppliersRouter = require('./routes/supplier/router'); +var employeesRouter = require('./routes/employee/router'); +var customerRouter = require('./routes/customer/router'); var app = express(); @@ -22,11 +26,16 @@ app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); +// // mongoose.connect('mongodb://localhost:27017/node-32-database'); +// mongoose.connect('mongodb://127.0.0.1:27017/node-32-database'); + app.use('/', indexRouter); app.use('/users', usersRouter); app.use('/products', productRouter); app.use('/categories', categoryRouter); app.use('/suppliers', suppliersRouter); +app.use('/employees', employeesRouter); +app.use('/customers', customerRouter); // catch 404 and forward to error handler diff --git a/data/suppliers.json b/data/suppliers.json index 8b77163..0637a08 100644 --- a/data/suppliers.json +++ b/data/suppliers.json @@ -1 +1 @@ -[{"id":1692094186261,"name":"Ron","email":"123@gmail.com","phoneNumber":"0903123213","address":"123 Van Cao"},{"id":1692194763889,"name":"Chi","email":"123gmail.com","phoneNumber":"0903333333","address":"123 Van Cao"}] \ No newline at end of file +[] \ No newline at end of file diff --git a/models/category.js b/models/category.js index 0ef424c..cb6c7ed 100644 --- a/models/category.js +++ b/models/category.js @@ -1,10 +1,29 @@ const mongoose = require('mongoose'); const { Schema, model } = mongoose; -const categorySchema = new Schema({ - name: { type: String, required: true }, - description: String, -}); +const categorySchema = new Schema( + { + name: { + type: String, + required: [true,'Tên danh mục không được bỏ trống'], + maxLength: [50,'Tên danh mục không vượt quá 50 kí tự'], + unique:[true, 'Tên danh mục không được trùng nhau'] + }, + description: { + type: String, + maxLength: [500,'Tên danh mục không vượt quá 500 kí tự'] + }, + isDeleted: { + type: Boolean, + required: true, + default: false + } + }, + { + versionKey: false, + timestamps: true, + } +); -const Category = model('Category', categorySchema); +const Category = model('Categories', categorySchema); module.exports = Category; \ No newline at end of file diff --git a/models/customer.js b/models/customer.js new file mode 100644 index 0000000..07ae9ab --- /dev/null +++ b/models/customer.js @@ -0,0 +1,79 @@ +const mongoose = require("mongoose"); +const { Schema, model } = mongoose; + +const customerSchema = new Schema( + { + firstName: { + type: String, + required: [true, "Tên nhân viên không được bỏ trống"], + maxLength: [20, "Tên nhân viên không vượt quá 20 kí tự"], + }, + + lastName: { + type: String, + required: [true, "Tên nhân viên không được bỏ trống"], + maxLength: [20, "Tên nhân viên không vượt quá 20 kí tự"], + }, + + email: { + type: String, + validate: { + validator: function (value) { + const emailRegex = + /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; + return emailRegex.test(value); + }, + message: `{value} không phải là email hợp lệ`, + }, + required: [true, "Email không được bỏ trống"], + unique: true, + }, + + phoneNumber: { + type: String, + validate: { + validator: function (value) { + const phoneRegex = /(84|0[3|5|7|8|9])+([0-9]{8})\b/g; + return phoneRegex.test(value); + }, + message: `{VALUE} không phải là số điện thoại hợp lệ`, + }, + unique: true, + }, + + isDeleted: { + type: Boolean, + required: true, + default: false, + }, + + address: { + type: String, + maxLength: [500, "Địa chỉ không vượt quá 500 kí tự"], + unique: true, + }, + + password: { + type: String, + validate: { + validator: function (value) { + const passRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/gm + return passRegex.test(value); + }, + message: `{VALUE} không phải là mật khẩu hợp lệ`, + }, + }, + + birthday: { + type: String + } + }, + { + versionKey: false, + timestamps: true, + } + +); + +const Customer = model("customers", customerSchema); +module.exports = Customer; diff --git a/models/employee.js b/models/employee.js new file mode 100644 index 0000000..fb27c5e --- /dev/null +++ b/models/employee.js @@ -0,0 +1,79 @@ +const mongoose = require("mongoose"); +const { Schema, model } = mongoose; + +const employeeSchema = new Schema( + { + firstName: { + type: String, + required: [true, "Tên nhân viên không được bỏ trống"], + maxLength: [20, "Tên nhân viên không vượt quá 20 kí tự"], + }, + + lastName: { + type: String, + required: [true, "Tên nhân viên không được bỏ trống"], + maxLength: [20, "Tên nhân viên không vượt quá 20 kí tự"], + }, + + email: { + type: String, + validate: { + validator: function (value) { + const emailRegex = + /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; + return emailRegex.test(value); + }, + message: `{value} không phải là email hợp lệ`, + }, + required: [true, "Email không được bỏ trống"], + unique: true, + }, + + phoneNumber: { + type: String, + validate: { + validator: function (value) { + const phoneRegex = /(84|0[3|5|7|8|9])+([0-9]{8})\b/g; + return phoneRegex.test(value); + }, + message: `{VALUE} không phải là số điện thoại hợp lệ`, + }, + unique: true, + }, + + isDeleted: { + type: Boolean, + required: true, + default: false, + }, + + address: { + type: String, + maxLength: [500, "Địa chỉ không vượt quá 500 kí tự"], + unique: true, + }, + + password: { + type: String, + validate: { + validator: function (value) { + const passRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/gm + return passRegex.test(value); + }, + message: `{VALUE} không phải là mật khẩu hợp lệ`, + }, + }, + + birthday: { + type: String + } + }, + { + versionKey: false, + timestamps: true, + } + +); + +const Employee = model("employees", employeeSchema); +module.exports = Employee; diff --git a/models/index.js b/models/index.js new file mode 100644 index 0000000..f91dd7c --- /dev/null +++ b/models/index.js @@ -0,0 +1,7 @@ +const Employee = require('./employee'); +const Customer = require('./customer'); + +module.exports = { + Employee, + Customer +} \ No newline at end of file diff --git a/models/supplier.js b/models/supplier.js index 437328d..8c0d0c8 100644 --- a/models/supplier.js +++ b/models/supplier.js @@ -1,10 +1,58 @@ -const mongoose = require('mongoose'); +const mongoose = require("mongoose"); const { Schema, model } = mongoose; -const supplierSchema = new Schema({ - name: { type: String, required: true }, - description: String, -}); +const supplierSchema = new Schema( + { + name: { + type: String, + required: [true, "Tên danh mục không được bỏ trống"], + maxLength: [50, "Tên danh mục không vượt quá 50 kí tự"], + unique: [true, "Tên danh mục không được trùng nhau"], + }, -const Category = model('Category', categorySchema); -module.exports = supplier; \ No newline at end of file + email: { + type: String, + validate: { + validator: function (value) { + const emailRegex = + /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; + return emailRegex.test(value); + }, + message: `{value} không phải là email hợp lệ`, + }, + required: [true, "Email không được bỏ trống"], + unique: true, + }, + + phoneNumber: { + type: Number, + validate: { + validator: function (value) { + const phoneRegex = /(84|0[3|5|7|8|9])+([0-9]{8})\b/g; + return phoneRegex.test(value); + }, + message: `{value} không phải là số điện thoại hợp lệ`, + }, + unique: true, + }, + + isDeleted: { + type: Boolean, + required: true, + default: false, + }, + + address: { + type: String, + maxLength: [500, "Địa chỉ không vượt quá 500 kí tự"], + } + }, + { + versionKey: false, + timestamps: true, + } + +); + +const Supplier = model("Suppliers", supplierSchema); +module.exports = Supplier; diff --git a/package.json b/package.json index cfa7206..3b6f8b4 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "cookie-parser": "~1.4.4", "debug": "~2.6.9", "express": "~4.16.1", + "express-generator": "^4.16.1", "http-errors": "~1.6.3", "jade": "~1.11.0", "mongodb": "^5.7.0", diff --git a/routes/category/controller.js b/routes/category/controller.js index 9e4e4a3..932e309 100644 --- a/routes/category/controller.js +++ b/routes/category/controller.js @@ -1,89 +1,164 @@ -const yup = require('yup'); -const fs = require('fs'); -let data = require('../../data/categories.json'); -const { writeFileSync, generationID, validateSchema, checkIdSchema, fuzzySearch } = require('../../utils'); -const Category = require('../../models/category') - -const getAll = (req, res, next) => { - res.send(data) -}; +const { default: mongoose } = require('mongoose'); -const getId = function (req, res, next) { - const { id } = req.params; +const { fuzzySearch } = require('../../utils'); - const validationSchema = yup.number(); +const Category = require('../../models/category'); - validationSchema - .validate(id) - .then(() => { - let result = data.find((x) => x.id == id); - if (result) { - return res.send({ code: 200, payload: result }); - } - return res.send(404, { message: "Not found" }); - }) - .catch((err) => res.send(400, { message: "Bad request" }) - ); -}; +// mongoose.connect('mongodb://localhost:27017/node-32-database'); +mongoose.connect('mongodb://127.0.0.1:27017/node-32-database'); -const getDetail = function (req, res, next) { - const { name } = req.query; - const filter = data.filter((item) => fuzzySearch(name).test(item.name)) - res.send(filter); +const getAll = async (req, res, next) => { + try { + const payload = await Category.find({ + isDeleted: false + }); + res.send(200, { + payload: payload, + message: "Tạo thành công" + }); + } catch (error) { + res.send(400, { + error, + message: "Tạo thất bại" + }); + } }; -const create = async function (req, res, next) { - const { name, isDeleted, description } = req.body; +//get detail +const getDetail = async function (req, res, next) { - const newP = { id: generationID(), name, isDeleted, description }; - if (data?.length > 0) { - await writeFileSync('data/categories.json', [...data, newP]); - } else { - await writeFileSync('data/categories.json', [newP]); - } - squadJSON = JSON.parse(fs.readFileSync('data/categories.json', 'utf8')); + try { + const { id } = req.params; + + const payload = await Category.findOne({ + _id: id, + isDeleted: false, + }); - res.send(200, { - payload: squadJSON, - message: "Tạo thành công" - }); + res.send(200, { + payload: payload, + message: "Tạo thành công" + }); + } catch (error) { + res.send(400, { + error, + message: "Tạo thất bại" + }); + } }; -const update = function (req, res, next) { +//search +const search = async function (req, res, next) { try { - const { id } = req.params; + const { name } = req.query; - const patchData = req.body; + const conditionFind = {isDeleted: false}; - let found = data.find((x) => x.id == id); - - if (found) { - for (let propertyName in patchData) { - found[propertyName] = patchData[propertyName]; - } - res.send({ ok: true, message: 'Updated' }); + if(name){ + conditionFind.name = fuzzySearch(name) } - res.send({ ok: false, message: 'Updated fail' }); + + const payload = await Category.find(conditionFind); + + res.send(200, { + payload: payload, + message: "Tim kiếm tên thành công" + }); } catch (error) { - res.send({ ok: false, message: 'Updated fail' }); + res.send(400, { + error, + message: "Tim kiếm tên thất bại" + }); } }; -const hardDelete = async function (req, res, next) { - const { id } = req.params; +/** CREATE */ - data = data.filter((x) => x.id.toString() !== id.toString()); +const create = async function (req, res, next) { + const { name, isDeleted, description } = req.body; + + try { + const newCategory = new Category({ + name, + description, + }); + + const payload = await newCategory.save(); + + res.send(200, { + payload: payload, + message: "Tạo thành công" + }); + } catch (err) { + res.send(400, { + err, + message: "Tạo thất bại" + }); + } +}; + +/** UPDATE */ +const update = async function (req, res, next) { + try { + const { id } = req.params; + + const payload = await Category.findOneAndUpdate( + { _id: id, isDeleted: false }, + { ...req.body }, + { new: true }, + ); + + if (payload) { + return res.send(200, { + payload, + message: "Cập nhập thành công" + }); + } + return res.send(404, { message: "Không tìm thấy" }); + } catch (error) { + console.log('««««« error »»»»»', error); + res.send(400, { + error, + message: "Cập nhập không thành công" + }); + } + }; - await writeFileSync('data/products.json', data); - res.send({ ok: true, message: 'Deleted' }); +/** DELETE */ +const hardDelete = async function (req, res, next) { + + try { + const { id } = req.params; + const payload = await Category.findOneAndUpdate( + { + _id: id, + isDeleted: false + }, + { isDeleted: true }, + { new: true } + ); + if (payload) { + + res.send(200, { + payload: payload, + message: "Xóa thành công" + }); + } + return res.send(200, 'Không tìm thấy danh mục') + } catch (err) { + res.send(400, { + err, + message: "Xóa thất bại" + }); + } }; module.exports = { getAll, - getId, getDetail, + search, create, hardDelete, update diff --git a/routes/category/router.js b/routes/category/router.js index 8f9d278..d84de16 100644 --- a/routes/category/router.js +++ b/routes/category/router.js @@ -1,32 +1,30 @@ var express = require('express'); var router = express.Router(); -const fs = require('fs'); - const { getAll, - getId, getDetail, + search, create, hardDelete, update } = require('./controller') const {updateProductSchema} = require('./validation') - -const data = require('../../data/categories.json'); -const { writeFileSync, generationID,validateSchema, checkIdSchema } = require('../../utils'); +const { validateSchema, checkIdSchema } = require('../../utils'); router.route('/') .get(getAll) - .post(create); + .post(validateSchema(updateProductSchema),create); -router.route('/:id') - .get(getId, validateSchema(checkIdSchema)) - .patch( update,validateSchema(checkIdSchema),validateSchema(updateProductSchema)) - .delete(hardDelete, validateSchema(checkIdSchema)); + +router.route('/search') +.get(search) -router.get('/search') - .get(getDetail) + +router.route('/:id') + .get( validateSchema(checkIdSchema), getDetail) + .put( validateSchema(checkIdSchema),validateSchema(updateProductSchema), update) + .delete(validateSchema(checkIdSchema), hardDelete); module.exports = router; diff --git a/routes/customer/controller.js b/routes/customer/controller.js new file mode 100644 index 0000000..e5cdcfc --- /dev/null +++ b/routes/customer/controller.js @@ -0,0 +1,171 @@ +const { default: mongoose } = require('mongoose'); + +const { fuzzySearch } = require('../../utils'); + +const {Customer} = require('../../models'); + +// mongoose.connect('mongodb://localhost:27017/node-32-database'); +mongoose.connect('mongodb://127.0.0.1:27017/node-32-database'); + + +const getAll = async (req, res, next) => { + try { + const payload = await Customer.find({ + isDeleted: false + }); + res.send(200, { + payload: payload, + message: "Tìm kiếm tất cả thành công" + }); + } catch (error) { + res.send(400, { + error, + message: "Tìm kiếm tất cả thất bại" + }); + } +}; + +//get detail +const getDetail = async function (req, res, next) { + try { + const { id } = req.params; + + const payload = await Customer.findOne({ + _id: id, + isDeleted: false, + }); + + res.send(200, { + payload: payload, + message: "Tìm kiếm thành công" + }); + } catch (error) { + res.send(400, { + error, + message: "Tìm kiếm không thành công hoặc sai mã Id" + }); + } +}; + +//search +const search = async function (req, res, next) { + try { + const { name } = req.query; + + const conditionFind = {isDeleted: false}; + + if(name){ + conditionFind.name = fuzzySearch(name) + }; + + const payload = await Customer.find(conditionFind); + + res.send(200, { + payload: payload, + message: "Tim kiếm tên thành công" + }); + } catch (error) { + res.send(400, { + error, + message: "Tim kiếm tên thất bại" + }); + } +}; + +/** CREATE */ + +const create = async function (req, res, next) { + const { firstName, lastName , birthday, email, phoneNumber, isDeleted, address, password } = req.body; + + try { + const newCustomer = new Customer({ + firstName, + lastName , + birthday, + email, + phoneNumber, + isDeleted, + address, + password + }); + + const payload = await newCustomer.save(); + + + res.send(200, { + payload: payload, + message: "Tạo thành công" + }); + } catch (err) { + res.send(400, { + err, + message: "Tạo thất bại" + }); + } +}; + +/** UPDATE */ +const update = async function (req, res, next) { + console.log('««««« saadas »»»»»'); + try { + const { id } = req.params; + + const payload = await Customer.findOneAndUpdate( + { _id: id, isDeleted: false }, + { ...req.body }, + { new: true }, + ); + + if (payload) { + return res.send(200, { + payload, + message: "Cập nhập thành công" + }); + } + return res.send(404, { message: "Không tìm thấy" }); + } catch (error) { + console.log('««««« error »»»»»', error); + res.send(400, { + error, + message: "Cập nhập không thành công" + }); + } + }; + + +/** DELETE */ +const hardDelete = async function (req, res, next) { + + try { + const { id } = req.params; + const payload = await Customer.findOneAndUpdate( + { + _id: id, + isDeleted: false + }, + { isDeleted: true }, + { new: true } + ); + if (payload) { + res.send(200, { + payload: payload, + message: "Xóa thành công" + }); + } + return res.send(200, 'Không tìm thấy tên nhà cung cấp') + } catch (err) { + res.send(400, { + err, + message: "Xóa thất bại" + }); + } +}; + +module.exports = { + getAll, + search, + getDetail, + create, + hardDelete, + update +}; \ No newline at end of file diff --git a/routes/customer/router.js b/routes/customer/router.js new file mode 100644 index 0000000..880aa52 --- /dev/null +++ b/routes/customer/router.js @@ -0,0 +1,28 @@ +var express = require('express'); +var router = express.Router(); + +const { + getAll, + getDetail, + create, + hardDelete, + update +} = require('./controller') + + +const { validateSchema, checkIdSchema } = require('../../utils'); +const { customerSchema } = require('./validation'); + +router.route('/') + .get(getAll) + .post(validateSchema(customerSchema), create); + +router.get('/search') + .get(getDetail) + +router.route('/:id') + .get(validateSchema(checkIdSchema), getDetail) + .put(validateSchema(checkIdSchema), validateSchema(customerSchema), update) + .delete(validateSchema(checkIdSchema), hardDelete); + +module.exports = router; diff --git a/routes/customer/validation.js b/routes/customer/validation.js new file mode 100644 index 0000000..fe16be7 --- /dev/null +++ b/routes/customer/validation.js @@ -0,0 +1,29 @@ +var express = require('express'); + +const yup = require('yup'); + +const customerSchema = yup.object({ + body: yup.object({ + firstName: yup.string().max(50).required(), + lastName: yup.string().max(50).required(), + isDeleted: yup.bool().required(), + email: yup.string().email(), + address: yup.string().max(500), + phoneNumber: yup + .string() + .matches(/(84|0[3|5|7|8|9])+([0-9]{8})\b/g, 'Số điện thoại sai định dạng') + // .test("phoneErr", "Số điện thoại sai rồi", (value) => { + // const regex = new RegExp(/(84|0[3|5|7|8|9])+([0-9]{8})\b/g); + // return regex.test(value); + // }) + .required('Required!'), + birthday: yup.date(), + password: yup.string() + .min(6, 'Minimum 6 characters') + .max(20, 'Minimum 12 characters') + .required('Required!'), + }), +}); +module.exports = { + customerSchema, +}; \ No newline at end of file diff --git a/routes/employee/controller.js b/routes/employee/controller.js new file mode 100644 index 0000000..acc24a1 --- /dev/null +++ b/routes/employee/controller.js @@ -0,0 +1,171 @@ +const { default: mongoose } = require('mongoose'); + +const { fuzzySearch } = require('../../utils'); + +const {Employee} = require('../../models'); + +// mongoose.connect('mongodb://localhost:27017/node-32-database'); +mongoose.connect('mongodb://127.0.0.1:27017/node-32-database'); + + +const getAll = async (req, res, next) => { + try { + const payload = await Employee.find({ + isDeleted: false + }); + res.send(200, { + payload: payload, + message: "Tạo thành công" + }); + } catch (error) { + res.send(400, { + error, + message: "Tạo thất bại" + }); + } +}; + +//get detail +const getDetail = async function (req, res, next) { + try { + const { id } = req.params; + + const payload = await Employee.findOne({ + _id: id, + isDeleted: false, + }); + + res.send(200, { + payload: payload, + message: "Tìm kiếm thành công" + }); + } catch (error) { + res.send(400, { + error, + message: "Tìm kiếm không thành công hoặc sai mã Id" + }); + } +}; + +//search +const search = async function (req, res, next) { + try { + const { name } = req.query; + + const conditionFind = {isDeleted: false}; + + if(name){ + conditionFind.name = fuzzySearch(name) + }; + + const payload = await Employee.find(conditionFind); + + res.send(200, { + payload: payload, + message: "Tim kiếm tên thành công" + }); + } catch (error) { + res.send(400, { + error, + message: "Tim kiếm tên thất bại" + }); + } +}; + +/** CREATE */ + +const create = async function (req, res, next) { + const { firstName, lastName , birthday, email, phoneNumber, isDeleted, address, password } = req.body; + + try { + const newEmployee = new Employee({ + firstName, + lastName , + birthday, + email, + phoneNumber, + isDeleted, + address, + password + }); + + const payload = await newEmployee.save(); + + + res.send(200, { + payload: payload, + message: "Tạo thành công" + }); + } catch (err) { + res.send(400, { + err, + message: "Tạo thất bại" + }); + } +}; + +/** UPDATE */ +const update = async function (req, res, next) { + console.log('««««« saadas »»»»»'); + try { + const { id } = req.params; + + const payload = await Employee.findOneAndUpdate( + { _id: id, isDeleted: false }, + { ...req.body }, + { new: true }, + ); + + if (payload) { + return res.send(200, { + payload, + message: "Cập nhập thành công" + }); + } + return res.send(404, { message: "Không tìm thấy" }); + } catch (error) { + console.log('««««« error »»»»»', error); + res.send(400, { + error, + message: "Cập nhập không thành công" + }); + } + }; + + +/** DELETE */ +const hardDelete = async function (req, res, next) { + + try { + const { id } = req.params; + const payload = await Employee.findOneAndUpdate( + { + _id: id, + isDeleted: false + }, + { isDeleted: true }, + { new: true } + ); + if (payload) { + res.send(200, { + payload: payload, + message: "Xóa thành công" + }); + } + return res.send(200, 'Không tìm thấy tên nhà cung cấp') + } catch (err) { + res.send(400, { + err, + message: "Xóa thất bại" + }); + } +}; + +module.exports = { + getAll, + search, + getDetail, + create, + hardDelete, + update +}; \ No newline at end of file diff --git a/routes/employee/router.js b/routes/employee/router.js new file mode 100644 index 0000000..60a2099 --- /dev/null +++ b/routes/employee/router.js @@ -0,0 +1,28 @@ +var express = require('express'); +var router = express.Router(); + +const { + getAll, + getDetail, + create, + hardDelete, + update +} = require('./controller') + + +const { validateSchema, checkIdSchema } = require('../../utils'); +const { employeeSchema } = require('./validation'); + +router.route('/') + .get(getAll) + .post(validateSchema(employeeSchema), create); + +router.get('/search') + .get(getDetail) + +router.route('/:id') + .get(validateSchema(checkIdSchema), getDetail) + .put(validateSchema(checkIdSchema), validateSchema(employeeSchema), update) + .delete(validateSchema(checkIdSchema), hardDelete); + +module.exports = router; diff --git a/routes/employee/validation.js b/routes/employee/validation.js new file mode 100644 index 0000000..197ea04 --- /dev/null +++ b/routes/employee/validation.js @@ -0,0 +1,29 @@ +var express = require('express'); + +const yup = require('yup'); + +const employeeSchema = yup.object({ + body: yup.object({ + firstName: yup.string().max(50).required(), + lastName: yup.string().max(50).required(), + isDeleted: yup.bool().required(), + email: yup.string().email(), + address: yup.string().max(500), + phoneNumber: yup + .string() + .matches(/(84|0[3|5|7|8|9])+([0-9]{8})\b/g, 'Số điện thoại sai định dạng') + // .test("phoneErr", "Số điện thoại sai rồi", (value) => { + // const regex = new RegExp(/(84|0[3|5|7|8|9])+([0-9]{8})\b/g); + // return regex.test(value); + // }) + .required('Required!'), + birthday: yup.date(), + password: yup.string() + .min(6, 'Minimum 6 characters') + .max(20, 'Minimum 12 characters') + .required('Required!'), + }), +}); +module.exports = { + employeeSchema, +}; \ No newline at end of file diff --git a/routes/product/router.js b/routes/product/router.js index 0c02235..1676c82 100644 --- a/routes/product/router.js +++ b/routes/product/router.js @@ -141,12 +141,12 @@ const { writeFileSync, generationID, validateSchema,checkIdSchema } = require('. /// FULL V-3: tách biệt và gộp các router router.route('/') .get(getAll) - .post(create); + .post(validateSchema(updateProductSchema), create); router.route('/:id') - .get(getId, validateSchema(checkIdSchema)) - .patch( update,validateSchema(checkIdSchema),validateSchema(updateProductSchema)) - .delete(hardDelete, validateSchema(checkIdSchema)); + .get(validateSchema(checkIdSchema), getId) + .patch(validateSchema(checkIdSchema),validateSchema(updateProductSchema), update) + .delete(validateSchema(checkIdSchema), hardDelete); router.get('/search') .get(getDetail) diff --git a/routes/supplier/controller.js b/routes/supplier/controller.js index a0a1988..d5d9c4b 100644 --- a/routes/supplier/controller.js +++ b/routes/supplier/controller.js @@ -1,86 +1,166 @@ -const yup = require('yup'); -const fs = require('fs'); -let data = require('../../data/suppliers.json'); -const { writeFileSync, generationID, validateSchema, checkIdSchema } = require('../../utils'); +const { default: mongoose } = require('mongoose'); -const getAll = (req, res, next) => { - res.send(data) -}; +const { fuzzySearch } = require('../../utils'); -const getId = function (req, res, next) { - const { id } = req.params; +const Supplier = require('../../models/supplier'); - const validationSchema = yup.number(); +// mongoose.connect('mongodb://localhost:27017/node-32-database'); +mongoose.connect('mongodb://127.0.0.1:27017/node-32-database'); - validationSchema - .validate(id) - .then(() => { - let result = data.find((x) => x.id == id); - if (result) { - return res.send({ code: 200, payload: result }); - } - return res.send(404, { message: "Not found" }); - }) - .catch((err) => res.send(400, { message: "Bad request" }) - ); +const getAll = async (req, res, next) => { + try { + const payload = await Supplier.find({ + isDeleted: false + }); + res.send(200, { + payload: payload, + message: "Tạo thành công" + }); + } catch (error) { + res.send(400, { + error, + message: "Tạo thất bại" + }); + } }; -const getDetail = function (req, res, next) { - const { price } = req.query; - const filter = data.filter((item) => item.price >= price) - res.send(filter); -}; +//get detail +const getDetail = async function (req, res, next) { + try { + const { id } = req.params; -const create = async function (req, res, next) { - const { name, isDelete, email, phoneNumber, address } = req.body; + const payload = await Supplier.findOne({ + _id: id, + isDeleted: false, + }); - const newP = { name, isDelete, email, phoneNumber, address, id: generationID() }; - if (data?.length > 0) { - await writeFileSync('data/suppliers.json', [...data, newP]); - } else { - await writeFileSync('data/suppliers.json', [newP]); + res.send(200, { + payload: payload, + message: "Tạo thành công" + }); + } catch (error) { + res.send(400, { + error, + message: "Tạo thất bại" + }); } - - res.send(200, { - payload: newP, - message: "Tạo thành công" - }); }; -const update = function (req, res, next) { +//search +const search = async function (req, res, next) { try { - const { id } = req.params; + const { name } = req.query; - const patchData = req.body; + const conditionFind = {isDeleted: false}; - let found = data.find((x) => x.id == id); + if(name){ + conditionFind.name = fuzzySearch(name) + }; - if (found) { - for (let propertyName in patchData) { - found[propertyName] = patchData[propertyName]; - } - res.send({ ok: true, message: 'Updated' }); - } - res.send({ ok: false, message: 'Updated fail' }); + const payload = await Supplier.find(conditionFind); + + res.send(200, { + payload: payload, + message: "Tim kiếm tên thành công" + }); } catch (error) { - res.send({ ok: false, message: 'Updated fail' }); + res.send(400, { + error, + message: "Tim kiếm tên thất bại" + }); } }; -const hardDelete = async function (req, res, next) { - const { id } = req.params; +/** CREATE */ + +const create = async function (req, res, next) { + const { name, email, phoneNumber, isDeleted, address } = req.body; + + try { + const newSupplier = new Supplier({ + name, + email, + phoneNumber, + address, + isDeleted + }); + + const payload = await newSupplier.save(); + + + res.send(200, { + payload: payload, + message: "Tạo thành công" + }); + } catch (err) { + res.send(400, { + err, + message: "Tạo thất bại" + }); + } +}; + +/** UPDATE */ +const update = async function (req, res, next) { + try { + const { id } = req.params; + + const payload = await Supplier.findOneAndUpdate( + { _id: id, isDeleted: false }, + { ...req.body }, + { new: true }, + ); + + if (payload) { + return res.send(200, { + payload, + message: "Cập nhập thành công" + }); + } + return res.send(404, { message: "Không tìm thấy" }); + } catch (error) { + console.log('««««« error »»»»»', error); + res.send(400, { + error, + message: "Cập nhập không thành công" + }); + } + }; + - data = data.filter((x) => x.id.toString() !== id.toString()); +/** DELETE */ +const hardDelete = async function (req, res, next) { - await writeFileSync('data/suppliers.json', data); + try { + const { id } = req.params; + const payload = await Supplier.findOneAndUpdate( + { + _id: id, + isDeleted: false + }, + { isDeleted: true }, + { new: true } + ); + if (payload) { - res.send({ ok: true, message: 'Deleted' }); + res.send(200, { + payload: payload, + message: "Xóa thành công" + }); + } + return res.send(200, 'Không tìm thấy tên nhà cung cấp') + } catch (err) { + res.send(400, { + err, + message: "Xóa thất bại" + }); + } }; module.exports = { getAll, - getId, + search, getDetail, create, hardDelete, diff --git a/routes/supplier/router.js b/routes/supplier/router.js index bd1e496..9a53b01 100644 --- a/routes/supplier/router.js +++ b/routes/supplier/router.js @@ -1,29 +1,28 @@ var express = require('express'); var router = express.Router(); -const fs = require('fs'); - const { getAll, - getId, getDetail, create, hardDelete, update } = require('./controller') -const {updateProductSchema} = require('./validation') + +const { validateSchema, checkIdSchema } = require('../../utils'); +const { supplierSchema } = require('./validation'); router.route('/') .get(getAll) - .post(create); - -router.route('/:id') - .get(validateSchema(checkIdSchema), getId) - .patch( validateSchema(checkIdSchema),validateSchema(updateProductSchema), update) - .delete( validateSchema(checkIdSchema),hardDelete); + .post(validateSchema(supplierSchema),create); router.get('/search') .get(getDetail) +router.route('/:id') + .get(validateSchema(checkIdSchema), getDetail) + .put(validateSchema(checkIdSchema), validateSchema(supplierSchema), update) + .delete(validateSchema(checkIdSchema), hardDelete); + module.exports = router; diff --git a/routes/supplier/validation.js b/routes/supplier/validation.js index 2e09b7c..5dba950 100644 --- a/routes/supplier/validation.js +++ b/routes/supplier/validation.js @@ -2,15 +2,15 @@ var express = require('express'); const yup = require('yup'); -const updateProductSchema = yup.object({ +const supplierSchema = yup.object({ body: yup.object({ name: yup.string().max(50).required(), isDeleted: yup.bool().required(), - email:yup.email(), + email:yup.string().email(), address: yup.string().max(500), phoneNumber: yup .string() - .matches(/(84|0[3|5|7|8|9])+([0-9]{8})\b/g, 'Số điện thoại sai rồi') + .matches(/(84|0[3|5|7|8|9])+([0-9]{8})\b/g, 'Số điện thoại sai định dạng') // .test("phoneErr", "Số điện thoại sai rồi", (value) => { // const regex = new RegExp(/(84|0[3|5|7|8|9])+([0-9]{8})\b/g); // return regex.test(value); @@ -19,5 +19,5 @@ const updateProductSchema = yup.object({ }), }); module.exports = { - updateProductSchema, + supplierSchema, }; \ No newline at end of file diff --git a/routes/suppliers.js b/routes/suppliers.js deleted file mode 100644 index 2d61fc3..0000000 --- a/routes/suppliers.js +++ /dev/null @@ -1,72 +0,0 @@ - -var express = require('express'); -var router = express.Router(); -const yup = require('yup'); -const fs = require('fs'); - -const data = require('../data/suppliers.json'); -const { writeFileSync, generationID, validateSchema } = require('../utils'); - -//////////////////GET -/* GET home page. */ -router.get('/', function (req, res, next) { - res.send(data); -}); - - -//////////////////POST -router.post('/', async function (req, res, next) { - const { name, email, phoneNumber, isDeleted = false, address } = req.body; - - const newP = { id: generationID(), name, email, phoneNumber, address }; - if (data?.length > 0) { - await writeFileSync('data/suppliers.json', [...data, newP]); - } else { - await writeFileSync('data/suppliers.json', [newP]); - } - - res.send(200, { - payload: newP, - message: "Tạo thành công" - }); -}); - -//////////////////PATCH -// const updateProductSchema = yup.object({ -// params: yup.object({ -// id: yup.number(), -// }), -// body: yup.object({ -// price: yup.number(), -// name: yup.string(), -// }), -// }); - -router.patch('/:id', function (req, res, next) { - const { id } = req.params; - const patchData = req.body; - - let found = data.find((x) => x.id == id); - - if (found) { - for (let propertyName in patchData) { - found[propertyName] = patchData[propertyName]; - } - res.send({ ok: true, message: 'Updated' }); - } - res.send({ ok: false, message: 'Updated fail' }); - - }); - - -//////////////////DETELE -router.delete('/:id', function (req, res, next) { - const { id } = req.params; - data = data.filter((x) => x.id.toString() !== id.toString()); - - console.log('««««« data »»»»»', data); - - res.send({ ok: true, message: 'Deleted' }); -}); - -module.exports = router; \ No newline at end of file diff --git a/utils/index.js b/utils/index.js index a0ed9ab..6a88c9e 100644 --- a/utils/index.js +++ b/utils/index.js @@ -1,5 +1,6 @@ const fs = require('fs'); const yup = require('yup'); +const ObjectId = require('mongodb').ObjectId; module.exports = { writeFileSync: (path, data) => { @@ -33,12 +34,20 @@ module.exports = { } }, + // checkIdSchema: yup.object({ + // params: yup.object({ + // id: yup.number(), + // }) + // }), checkIdSchema: yup.object({ params: yup.object({ - id: yup.number(), - }) + id: yup.string().test('inValid', 'ID sai định dạng', (value) => { + return ObjectId.isValid(value); + }), + }), }), + fuzzySearch: (text) => { const regex = text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); diff --git a/yarn.lock b/yarn.lock index ca2c580..b889424 100644 --- a/yarn.lock +++ b/yarn.lock @@ -190,6 +190,11 @@ cliui@^2.1.0: right-align "^0.1.1" wordwrap "0.0.2" +commander@2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== + commander@2.8.x: version "2.8.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" @@ -306,6 +311,11 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== +ejs@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0" + integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -321,6 +331,17 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +express-generator@^4.16.1: + version "4.16.1" + resolved "https://registry.yarnpkg.com/express-generator/-/express-generator-4.16.1.tgz#9b7989b3cdffbea714d549db57fe53c21cb75d70" + integrity sha512-tWYEx5Y/Llos2qC6yAETmdqEMEPqNUzJ8btGcSZ2zSr8RYOalzffhvh9zx5OQTctvOgJ9kKYxyvFGAIuUuF/wA== + dependencies: + commander "2.15.1" + ejs "2.6.1" + minimatch "3.0.4" + mkdirp "0.5.1" + sorted-object "2.0.1" + express@~4.16.1: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" @@ -575,6 +596,13 @@ mime@1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== +minimatch@3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -582,11 +610,23 @@ minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q== + minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +mkdirp@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA== + dependencies: + minimist "0.0.8" + mkdirp@~0.5.0: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" @@ -890,6 +930,11 @@ socks@^2.7.1: ip "^2.0.0" smart-buffer "^4.2.0" +sorted-object@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/sorted-object/-/sorted-object-2.0.1.tgz#7d631f4bd3a798a24af1dffcfbfe83337a5df5fc" + integrity sha512-oKAAs26HeTu3qbawzUGCkTOBv/5MRrcuJyRWwbfEnWdpXnXsj+WEM3HTvarV73tMcf9uBEZNZoNDVRL62VLxzA== + source-map@0.4.x: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"