diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/README.md b/README.md index 38e49cd..2948fdc 100644 --- a/README.md +++ b/README.md @@ -1 +1,108 @@ -# mongodb-crud \ No newline at end of file +# mongodb-crud + +## Running: +> sudo service mongod start
+> connection @robomongo
+> mongo
+> npm run dev + +## **Usage** +Menu URL +http://localhost:3000 + +Find All Books (GET) : /books + +Find By ISBN (GET) : /book/search?isbn= + +Create Book (POST) : /book + +Update Book (PUT) : /book/:isbn + +Delete Book (DELETE) : /book/:isbn + +Find All Customers (GET) : /customers + +Find By Member ID (GET) : /customer/search?memberid= + +Create Member (POST) : /customer + +Update Member (PUT) : /customer/:memberid + +Delete Member (DELETE) : /customer/:memberid + +Find All Transaction (GET) : /transactions + +Find By ID (GET) : /transaction/search?id= + +Create Transaction (POST) : /transaction + +Update Transaction (PUT) : /transaction/:id + +Delete Transaction (DELETE) : /transaction/:id + +## Using Seed + +Seed books (GET) : /seeds/books +Seed customers (GET) : /seeds/customers +Seed transactions (GET) : /seeds/transactions + +## Create Schema +1. use library +2. db.createCollection("books") +3. db.createCollection("transactions") +4. db.books.insert([ + { + isbn: '978-1-60309-057-5', + title: 'Dragon Puncher', + author: 'James Kochalka', + category: 'All Ages', + stock: 3 + }, + { + isbn: '978-1-891830-77-8', + title: 'Every Girl is the End of the World for Me', + author: 'Jeffrey Brown', + category: 'Mature (16+)', + stock: 5 + } +]) +5. db.getCollection('books').find({}) +6. db.transactions.insert([ + { + memberid: 'CL0001', + days: 6, + outdate: ISODate("2016-04-19T14:56:59.301Z"), + duedate: ISODate("2016-04-25T14:56:59.301Z"), + indate: ISODate("2016-04-27T14:56:59.301Z"), + fine: 2000, + booklist: + [ + { + "$ref": "books", + "$isbn": "978-1-60309-057-5", + "$db": "academic" + }, + { + "$ref": "books", + "$isbn": "978-1-891830-77-8", + "$db": "academic" + } + ] + } +]) +7. db.customers.insert([ + { + name: 'Isumi Karina', + memberid: 'CL0001', + address: 'Jakarta', + zipcode: '10340', + phone: '08159070289' + }, + { + name: 'Aiko Diandra', + memberid: 'CL0002', + address: 'Bandung', + zipcode: '12345', + phone: '081234567' + } +]) diff --git a/app.js b/app.js new file mode 100644 index 0000000..22fcab9 --- /dev/null +++ b/app.js @@ -0,0 +1,51 @@ +var express = require('express'); +var path = require('path'); +var favicon = require('serve-favicon'); +var logger = require('morgan'); +var cookieParser = require('cookie-parser'); +var bodyParser = require('body-parser'); + +var index = require('./routes/index'); +var users = require('./routes/users'); +var seed = require('./routes/seed'); + +var mongoose = require('mongoose'); +mongoose.connect('mongodb://localhost/library') + +var app = express(); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'ejs'); + +// uncomment after placing your favicon in /public +//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); +app.use(logger('dev')); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, 'public'))); + +app.use('/', index); +app.use('/users', users); +app.use('/seeds', seed); + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + var err = new Error('Not Found'); + err.status = 404; + next(err); +}); + +// error handler +app.use(function(err, req, res, next) { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get('env') === 'development' ? err : {}; + + // render the error page + res.status(err.status || 500); + res.render('error'); +}); + +module.exports = app; diff --git a/bin/www b/bin/www new file mode 100755 index 0000000..1efba33 --- /dev/null +++ b/bin/www @@ -0,0 +1,90 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var app = require('../app'); +var debug = require('debug')('mongodb-crud:server'); +var http = require('http'); + +/** + * Get port from environment and store in Express. + */ + +var port = normalizePort(process.env.PORT || '3000'); +app.set('port', port); + +/** + * Create HTTP server. + */ + +var server = http.createServer(app); + +/** + * Listen on provided port, on all network interfaces. + */ + +server.listen(port); +server.on('error', onError); +server.on('listening', onListening); + +/** + * Normalize a port into a number, string, or false. + */ + +function normalizePort(val) { + var port = parseInt(val, 10); + + if (isNaN(port)) { + // named pipe + return val; + } + + if (port >= 0) { + // port number + return port; + } + + return false; +} + +/** + * Event listener for HTTP server "error" event. + */ + +function onError(error) { + if (error.syscall !== 'listen') { + throw error; + } + + var bind = typeof port === 'string' + ? 'Pipe ' + port + : 'Port ' + port; + + // handle specific listen errors with friendly messages + switch (error.code) { + case 'EACCES': + console.error(bind + ' requires elevated privileges'); + process.exit(1); + break; + case 'EADDRINUSE': + console.error(bind + ' is already in use'); + process.exit(1); + break; + default: + throw error; + } +} + +/** + * Event listener for HTTP server "listening" event. + */ + +function onListening() { + var addr = server.address(); + var bind = typeof addr === 'string' + ? 'pipe ' + addr + : 'port ' + addr.port; + debug('Listening on ' + bind); +} diff --git a/controller/controllerBooks.js b/controller/controllerBooks.js new file mode 100644 index 0000000..8b3acb3 --- /dev/null +++ b/controller/controllerBooks.js @@ -0,0 +1,74 @@ +'use strict' +var Book = require('../models/book.js'); + +module.exports = { + + findAllBooks : function(req, res, next) { + Book.find({}, function(err, books){ + if (err) { + res.send(err) + } else { + res.send(books) + } + }) + }, + + findByIsbn : function(req, res, next) { + Book.find( + { + isbn: req.query.isbn + }, function(err, books){ + if (err) { + res.send(err) + } else { + res.send(books); + } + }) + }, + + createBook : function(req, res, next) { + var newBook = Book( + { + isbn: req.body.isbn, + title: req.body.title, + author: req.body.author, + category: req.body.category, + stock: req.body.stock + }) + + newBook.save(function(err){ + if (err) { + res.send(err) + } else { + res.send(`${req.body.title} has been created`) + } + }) + }, + + updateBook : function(req, res, next) { + Book.findOneAndUpdate( + { + isbn: req.params.isbn + }, req.body, {new : true}, function(err, books){ + if (err) { + res.send(err) + } else { + res.send(books); + } + }) + }, + + deleteBook : function(req, res, next) { + Book.findOneAndRemove( + { + isbn: req.params.isbn + }, function(err){ + if (err) { + res.send(err) + } else { + res.send(`Book: ${req.params.isbn} has been removed`) + } + }) + } + +} diff --git a/controller/controllerCustomers.js b/controller/controllerCustomers.js new file mode 100644 index 0000000..f39e7d9 --- /dev/null +++ b/controller/controllerCustomers.js @@ -0,0 +1,74 @@ +'use strict' +var Customer = require('../models/customer.js'); + +module.exports = { + + findAllCustomers : function(req, res, next) { + Customer.find({}, function(err, customers){ + if (err) { + res.send(err) + } else { + res.send(customers) + } + }) + }, + + findByMemberId : function(req, res, next) { + Customer.find( + { + memberid: req.query.memberid + }, function(err, customers){ + if (err) { + res.send(err) + } else { + res.send(customers) + } + }) + }, + + createMember : function(req, res, next) { + var newMember = Customer( + { + name: req.body.name, + memberid: req.body.memberid, + address: req.body.address, + zipcode: req.body.zipcode, + phone: req.body.phone + }) + + newMember.save(function(err){ + if (err) { + res.send(err) + } else { + res.send(`User ${req.body.name} has been created`) + } + }) + }, + + updateMember : function(req, res, next) { + Customer.findOneAndUpdate( + { + memberid: req.params.memberid + }, req.body, {new : true}, function(err, customers){ + if (err) { + res.send(err) + } else { + res.send(customers) + } + }) + }, + + deleteMember : function(req, res, next) { + Customer.findOneAndRemove( + { + memberid: req.params.memberid + }, function(err){ + if (err) { + res.send(err) + } else { + res.send(`Member: ${req.params.memberid} has been removed`); + } + }) + } + +} diff --git a/controller/controllerTransactions.js b/controller/controllerTransactions.js new file mode 100644 index 0000000..ea03d4a --- /dev/null +++ b/controller/controllerTransactions.js @@ -0,0 +1,99 @@ +'use strict' +var Transaction = require('../models/transaction.js'); + +module.exports = { + + findAllTransactions : function(req, res, next) { + Transaction.find({}, function(err, transactions){ + if (err) { + res.send(err) + } else { + res.send(transactions) + } + }) + }, + + findById : function(req, res, next) { + Transaction.find( + { + _id: req.query.id + }, function(err,transactions){ + if (err) { + res.send(err) + } else { + res.send(transactions) + } + }) + }, + + createTransaction : function(req, res, next) { + var newTransaction = Transaction( + { + memberid: req.body.memberid, + days: req.body.days, + out_date: new Date(), + due_date: new Date(), + in_date: new Date(), + fine: req.body.fine, + booklist:[] + }) + + newTransaction.save(function(err){ + if (err) { + res.send(err) + } else { + res.send(`Transaction: ${req.body.memberid} has been created`) + } + }) + }, + + addBook : function (req, res) { + Transaction.update( + { + _id: req.params.id + }, + { + $push: {booklist:{bookid: req.body.bookid, qty: req.body.qty}}}, + {upsert: true}).then(function(data){ + res.send(data) + }) + }, + + deleteBook : function (req, res) { + Transaction.update( + { + _id: req.params.id + }, + {$pull: {booklist:{bookid: req.body.bookid, qty: req.body.qty}}}, + {upsert: true}).then(function(data){ + res.send(data) + }) + }, + + updateTransaction : function(req, res, next) { + Transaction.findOneAndUpdate( + { + _id: req.params.id + }, req.body, {new : true}, function(err, data){ + if (err) { + res.send(err) + } else { + res.send(data) + } + }) + }, + + deleteTransaction : function(req, res, next) { + Transaction.findOneAndRemove( + { + _id: req.params.id + }, function(err){ + if (err) { + res.send(err) + } else { + res.send(`Transaction: ${req.params.id} has been removed`); + } + }) + } + +} diff --git a/models/book.js b/models/book.js new file mode 100644 index 0000000..7326735 --- /dev/null +++ b/models/book.js @@ -0,0 +1,14 @@ +'use strict' +var mongoose = require('mongoose'); + +var bookSchema = mongoose.Schema({ + isbn: String, + title: String, + author: String, + category: String, + stock: Number +}) + +var book = mongoose.model('Book', bookSchema) + +module.exports = book diff --git a/models/customer.js b/models/customer.js new file mode 100644 index 0000000..25aa207 --- /dev/null +++ b/models/customer.js @@ -0,0 +1,15 @@ +'use strict' +var mongoose = require('mongoose'); +var Schema = mongoose.Schema + +var customerSchema = Schema({ + name: String, + memberid: String, + address: String, + zipcode: String, + phone: String +}) + +var customer = mongoose.model('Customer', customerSchema) + +module.exports = customer diff --git a/models/transaction.js b/models/transaction.js new file mode 100644 index 0000000..db23b21 --- /dev/null +++ b/models/transaction.js @@ -0,0 +1,18 @@ +'use strict' +var mongoose = require('mongoose'); +var Schema = mongoose.Schema + +var transactionSchema = Schema({ + memberid: String, + days: Number, + outdate: Date, + duedate: Date, + indate: Date, + fine: Number, + booklist: + [{ type: Schema.Types.ObjectId, ref: 'Book' }] +}) + +var transaction = mongoose.model('Transaction', transactionSchema) + +module.exports = transaction diff --git a/package.json b/package.json new file mode 100644 index 0000000..cac2262 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "mongodb-crud", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www", + "dev": "nodemon ./bin/www" + }, + "dependencies": { + "body-parser": "~1.16.0", + "cookie-parser": "~1.4.3", + "debug": "~2.6.0", + "ejs": "~2.5.5", + "express": "~4.14.1", + "morgan": "~1.7.0", + "nodemon": "^1.11.0", + "serve-favicon": "~2.3.2" + } +} diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css new file mode 100644 index 0000000..9453385 --- /dev/null +++ b/public/stylesheets/style.css @@ -0,0 +1,8 @@ +body { + padding: 50px; + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; +} + +a { + color: #00B7FF; +} diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..23443c7 --- /dev/null +++ b/routes/index.js @@ -0,0 +1,46 @@ +var express = require('express'); +var router = express.Router(); +var controllerBooks = require('../controller/controllerBooks') +var controllerCustomers = require('../controller/controllerCustomers') +var controllerTransactions = require('../controller/controllerTransactions') + +/* GET home page. */ +router.get('/', function(req, res, next){ + res.send('Menu URL\nhttp://localhost:3000\n\nFind All Books (GET): /books\n\nFind By ISBN (GET): /book/search?isbn=\n\nCreate Book (POST): /book\n\nUpdate Book (PUT): /book/:isbn\n\nDelete Book (DELETE): /book/:isbn\n\nFind All Customers (GET): /customers\n\nFind By Member ID (GET): /customer/search?memberid=\n\nCreate Member (POST): /customer\n\nUpdate Member (PUT): /customer/:memberid\n\nDelete Member (DELETE): /customer/:memberid\n\nFind All Transaction (GET): /transactions\n\nFind By ID (GET): /transaction/search?id=\n\nCreate Transaction (POST): /transaction\n\nUpdate Transaction (PUT): /transaction/:id\n\nDelete Transaction (DELETE): /transaction/:id') +}); + +router.get('/books', controllerBooks.findAllBooks); + +router.get('/book/search', controllerBooks.findByIsbn); + +router.post('/book', controllerBooks.createBook); + +router.put('/book/:isbn', controllerBooks.updateBook); + +router.delete('/book/:isbn', controllerBooks.deleteBook); + +router.get('/customers', controllerCustomers.findAllCustomers); + +router.get('/customer/search', controllerCustomers.findByMemberId); + +router.post('/customer', controllerCustomers.createMember); + +router.put('/customer/:memberid', controllerCustomers.updateMember); + +router.delete('/customer/:memberid', controllerCustomers.deleteMember); + +router.get('/transactions', controllerTransactions.findAllTransactions); + +router.get('/transaction/search', controllerTransactions.findById); + +router.post('/transaction', controllerTransactions.createTransaction); + +router.put('/transaction/addbook/:id', controllerTransactions.addBook); + +router.put('/transaction/deletebook/:id', controllerTransactions.deleteBook); + +router.put('/transaction/:id', controllerTransactions.updateTransaction); + +router.delete('/transaction/:id', controllerTransactions.deleteTransaction); + +module.exports = router; diff --git a/routes/seed.js b/routes/seed.js new file mode 100644 index 0000000..5a3670e --- /dev/null +++ b/routes/seed.js @@ -0,0 +1,90 @@ +var express = require('express'); +var router = express.Router(); +var Book = require('../models/book') +var Transaction = require('../models/transaction') +var Customer = require('../models/customer') + +/* GET home page. */ +router.get('/books', function(req, res, next) { + var newbooks = [ + { + isbn: '978-1-60309-057-5', + title: 'Dragon Puncher', + author: 'James Kochalka', + category: 'All Ages', + stock: 3 + }, + { + isbn: '978-1-891830-77-8', + title: 'Every Girl is the End of the World for Me', + author: 'Jeffrey Brown', + category: 'Mature (16+)', + stock: 5 + }, + { + isbn: '978-1-891830-77-0', + title: 'Perahu Kertas', + author: 'Dee', + category: 'Mature (16+)', + stock: 4 + }, + { + isbn: '978-1-891830-88-0', + title: 'Madre', + author: 'Dee', + category: 'Mature (16+)', + stock: 2 + }] + + Book.create(newbooks, function (err, data) { + if (err) { + res.send(err) + } else { + res.send(data) + } + }) +}); + +router.get('/transactions', function(req, res, next) { + var newtransaction = new Transaction( + { + memberid: 'CL0001', + days: 6, + outdate: '2016-04-19', + duedate: '2016-04-25', + indate: '2016-04-27', + fine: 2000, + booklist: ["58b692a4e10c941ec093c671", "58b692a4e10c941ec093c672"] + } + ) + newtransaction.save() + res.send('Seed Transaction Success!') +}); + +router.get('/customers', function(req, res, next) { + var newcustomers = [ + { + name: 'Isumi Karina', + memberid: 'CL0001', + address: 'Jakarta', + zipcode: '10340', + phone: '08159070289' + }, + { + name: 'Aiko Diandra', + memberid: 'CL0002', + address: 'Bandung', + zipcode: '12345', + phone: '081234567' + }] + + Customer.create(newcustomers, function(err, data) { + if (err) { + res.send(err) + } else { + res.send(data) + } + }) +}); + +module.exports = router; diff --git a/routes/users.js b/routes/users.js new file mode 100644 index 0000000..623e430 --- /dev/null +++ b/routes/users.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); + +/* GET users listing. */ +router.get('/', function(req, res, next) { + res.send('respond with a resource'); +}); + +module.exports = router; diff --git a/seed/book.js b/seed/book.js new file mode 100644 index 0000000..a06248b --- /dev/null +++ b/seed/book.js @@ -0,0 +1,32 @@ +'use strict' +var mongoose = require('mongoose'); + +var Book = require('../models/book') + +var mongoose = require('mongoose'); +mongoose.connect('mongodb://localhost/library') + +var newbook = new Book( + { + isbn: '978-1-60309-057-5', + title: 'Dragon Puncher', + author: 'James Kochalka', + category: 'All Ages', + stock: 3 + } +) + +var newbook2 = new Book( + { + isbn: '978-1-891830-77-8', + title: 'Every Girl is the End of the World for Me', + author: 'Jeffrey Brown', + category: 'Mature (16+)', + stock: 5 + } +) + +newbook.save() +newbook2.save() +console.log(newbook); +process.exit(1) diff --git a/views/error.ejs b/views/error.ejs new file mode 100644 index 0000000..7cf94ed --- /dev/null +++ b/views/error.ejs @@ -0,0 +1,3 @@ +

<%= message %>

+

<%= error.status %>

+
<%= error.stack %>
diff --git a/views/index.ejs b/views/index.ejs new file mode 100644 index 0000000..7b7a1d6 --- /dev/null +++ b/views/index.ejs @@ -0,0 +1,11 @@ + + + + <%= title %> + + + +

<%= title %>

+

Welcome to <%= title %>

+ +