diff --git a/.gitignore b/.gitignore index e43b0f9..f923ceb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ .DS_Store +node_modules +npm-debug.log +db/ diff --git a/app.js b/app.js new file mode 100644 index 0000000..f5bd25b --- /dev/null +++ b/app.js @@ -0,0 +1,68 @@ +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'); + +// establish our routes based on route files +var routes = require('./routes/index'); +var movies = require('./routes/movies'); +var customers = require('./routes/customers'); +var rentals = require('./routes/rentals'); + + +var app = express(); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'jade'); + +// 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'))); + +// Establishes our routes +app.use('/', routes); +app.use('/customers', customers); +app.use('/movies', movies); +app.use('/rentals', rentals); + + +// 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 handlers + +// development error handler +// will print stacktrace +if (app.get('env') === 'development') { + app.use(function(err, req, res, next) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: err + }); + }); +} + +// production error handler +// no stacktraces leaked to user +app.use(function(err, req, res, next) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: {} + }); +}); + + +module.exports = app; diff --git a/bin/www b/bin/www new file mode 100755 index 0000000..cc43085 --- /dev/null +++ b/bin/www @@ -0,0 +1,90 @@ +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var app = require('../app'); +var debug = require('debug')('C3Projects--VideoStoreAPI: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/controllers/customers.js b/controllers/customers.js new file mode 100644 index 0000000..d5d1223 --- /dev/null +++ b/controllers/customers.js @@ -0,0 +1,52 @@ +"use strict"; + +var Customer = require('../customers'); +var customer = new Customer(); + +var sortCustomers = function(sort_type, params, res) { + var records_per_page = params.records_per_page; + var offset = params.offset; + var customers = customer.sort_by(sort_type, records_per_page, offset, function(customers) { + return res.status(200).json(customers); + }); +}; + +exports.customersController = { + + all: function all(req, res) { + var customers = customer.all(function(customers) { + return res.status(200).json(customers); + }); + }, + + registered_at_sort: function registered_at_sort(req, res) { + var sort_type = "registered_at"; + sortCustomers(sort_type, req.params, res); + }, + + name_sort: function name_sort(req, res) { + var sort_type = "name"; + sortCustomers(sort_type, req.params, res); + }, + + postal_code_sort: function postal_code_sort(req, res) { + var sort_type = "postal_code"; + sortCustomers(sort_type, req.params, res); + }, + + current_rentals: function current_rentals(req, res) { + var id = req.params.id; + + customer.current_rentals(id, function(current_rentals) { + return res.status(200).json(current_rentals); + }); + }, + + past_rentals: function past_rentals(req, res) { + var id = req.params.id; + + customer.past_rentals(id, function(past_rentals) { + return res.status(200).json(past_rentals); + }); + } +} diff --git a/controllers/movies.js b/controllers/movies.js new file mode 100644 index 0000000..8f54d0d --- /dev/null +++ b/controllers/movies.js @@ -0,0 +1,82 @@ +"use strict"; + +var Movie = require('../movies'); +var movie = new Movie(); + +var sortMovies = function (sort_type, params, res) { + var records_per_page = params.records_per_page; + var offset = params.offset; + var movies = movie.sort_by(sort_type, records_per_page, offset, function(movies){ + return res.status(200).json(movies); + }); +} + +exports.moviesController = { + + all: function all(req, res) { + var movies = movie.all(function(movies) { + return res.status(200).json(movies); + }); + }, + + release_date_sort: function release_date_sort(req, res) { + var sort_type = "release_date"; + sortMovies(sort_type, req.params, res); + }, + + title_sort: function title_sort(req, res) { + var sort_type = "title"; + sortMovies(sort_type, req.params, res); + }, + + movie_info: function movie_info(req, res) { + var movie_title = req.params.title; + + movie.movie_info(movie_title, function(movie_info) { + return res.status(200).json(movie_info); + }); + }, + + current_customers: function current_customers(req, res) { + var movie_title = req.params.title; + + movie.current_customers(movie_title, function(current_customers) { + return res.status(200).json(current_customers); + }); + }, + + past_customers: function past_customers(req, res) { + var movie_title = req.params.title; + + movie.past_customers(movie_title, function(past_customers) { + return res.status(200).json(past_customers); + }); + }, + + past_customers_id_sort: function past_customers_id_sort(req, res) { + var movie_title = req.params.title; + var sort_type = "customers.id"; + + movie.past_customers_sort(movie_title, sort_type, function(past_customers_sorted_by_id) { + return res.status(200).json(past_customers_sorted_by_id); + }); + }, + + past_customers_name_sort: function past_customers_name_sort(req, res) { + var movie_title = req.params.title; + var sort_type = "customers.name"; + + movie.past_customers_sort(movie_title, sort_type, function(past_customers_sorted_by_name) { + return res.status(200).json(past_customers_sorted_by_name); + }); + }, + + past_customers_checkout_date_sort: function past_customers_checkout_date_sort(req, res) { + var movie_title = req.params.title; + var sort_type = "rentals.check_out"; + + movie.past_customers_sort(movie_title, sort_type, function(past_customers_sorted_by_checkout_date) { + return res.status(200).json(past_customers_sorted_by_checkout_date); + }); + } +} diff --git a/controllers/rentals.js b/controllers/rentals.js new file mode 100644 index 0000000..c9437a1 --- /dev/null +++ b/controllers/rentals.js @@ -0,0 +1,46 @@ +"use strict"; + +var Rental = require('../rentals'); +var rental = new Rental(); + +exports.rentalsController = { + all_rentals: function all_rentals(req, res) { + var rentals = rental.all_rentals(function(rentals) { + return res.status(200).json(rentals); + }); + }, + + current_customers: function current_customers(req, res) { + var movie_title = req.params.movie_title; + + rental.current_customers(movie_title, function(current_customers){ + return res.status(200).json(current_customers); + }); + }, + + rental_log: function rental_log(req, res) { + var movie_title = req.params.movie_title; + + rental.rental_log(movie_title, function(rental_log){ + return res.status(200).json(rental_log); + }); + }, + + overdue: function overdue(req, res) { + rental.overdue(function(overdue) { + return res.status(200).json(overdue); + }); + }, + + check_out: function check_out(req, res) { + rental.check_out(req.body, function(check_out) { + return res.status(200).json(check_out); + }); + }, + + check_in: function check_in(req, res) { + rental.check_in(req.body, function(check_in) { + return res.status(200).json(check_in); + }); + } +}; diff --git a/customers.js b/customers.js new file mode 100644 index 0000000..6ca979b --- /dev/null +++ b/customers.js @@ -0,0 +1,24 @@ +"use-strict"; +var sqlite3 = require('sqlite3').verbose(); + +function Customer() { + this.table_name = "customers"; +} + +Customer.prototype = require('./database'); + +Customer.prototype.current_rentals = function(id, callback) { + // list of current rentals out based on customer id + this.query("SELECT * FROM rentals WHERE customer_id=" + id + " AND check_in IS NULL;", function(res) { + callback(res); + }); +}; + +Customer.prototype.past_rentals = function(id, callback) { + // list of past rentals based on customer id + this.query("SELECT * FROM rentals WHERE customer_id=" + id + " AND check_in IS NOT NULL ORDER BY check_out" + ";", function(res) { + callback(res); + }); +}; + +module.exports = Customer; diff --git a/database.js b/database.js new file mode 100644 index 0000000..a82f9b9 --- /dev/null +++ b/database.js @@ -0,0 +1,51 @@ +"use-strict"; +var sqlite3 = require('sqlite3').verbose(); +var db_env = process.env.DB || 'development'; + +// Here we will define our instance methods +module.exports = { + query: function(statement, callback) { // shared + var db = new sqlite3.Database('db/' + db_env + '.db'); + db.serialize(function() { + // below: this is the callback pattern...parameters(ERRORS, RESULT) + db.all(statement, function(err, res) { + // console.log(statement); + // console.log(err); + // error handling looks like -> if (err) { }; + if (callback) { callback(res); } + }); + }); + + db.close(); + }, + + all: function(callback) { // shared + this.query("SELECT * FROM " + this.table_name + ";", function(res) { + callback(res); + }); + }, + + sort_by: function(sort_type, records_per_page, offset, callback) { // shared + this.query("SELECT * FROM " + this.table_name + " ORDER BY " + sort_type + " LIMIT " + records_per_page + " OFFSET " + offset + ";", function(res) { + callback(res); + }); + }, + + formatDate: function(date) { // shared + var dateObj = new Date(date); + var month = (dateObj.getUTCMonth() + 1).toString(); //months from 1-12 + var day = (dateObj.getUTCDate()).toString(); + var year = (dateObj.getUTCFullYear()).toString(); + var newDate; + + if (month.length == 1) { // This will ensure month is two digits + month = "0" + month; + } + + if (day.length == 1) { // This will ensure day is two digits + day = "0" + day; + } + + return parseInt(year + month + day); + } +}; diff --git a/movies.js b/movies.js new file mode 100644 index 0000000..a35b21c --- /dev/null +++ b/movies.js @@ -0,0 +1,53 @@ +"use-strict"; +var sqlite3 = require('sqlite3').verbose(); + +function Movie() { + this.table_name = "movies"; +} + +Movie.prototype = require('./database'); + +Movie.prototype.movie_info = function(movie_title, callback) { + this.query("SELECT * FROM " + this.table_name + " WHERE title LIKE '%" + movie_title + "%';", function(res) { + callback(res); + }); +}; + +Movie.prototype.current_customers = function(movie_title, callback) { + this.query("SELECT customers.id, customers.name, customers.registered_at, \ + customers.address, customers.city, customers.state, \ + customers.postal_code, customers.phone, customers.account_credit \ + FROM customers, rentals \ + WHERE customers.id=rentals.customer_id \ + AND rentals.movie_title LIKE '%" + movie_title + "%' \ + AND rentals.check_in IS NULL;", function(res) { + callback(res); + }); +}; + +Movie.prototype.past_customers = function(movie_title, callback) { + this.query("SELECT customers.id, customers.name, customers.registered_at, \ + customers.address, customers.city, customers.state, \ + customers.postal_code, customers.phone, customers.account_credit \ + FROM customers, rentals \ + WHERE customers.id=rentals.customer_id \ + AND rentals.movie_title LIKE '%" + movie_title + "%' \ + AND rentals.check_in IS NOT NULL;", function(res) { + callback(res); + }); +}; + +Movie.prototype.past_customers_sort = function(movie_title, sort_type, callback) { + this.query("SELECT customers.id, customers.name, customers.registered_at, \ + customers.address, customers.city, customers.state, \ + customers.postal_code, customers.phone, customers.account_credit \ + FROM customers, rentals \ + WHERE customers.id=rentals.customer_id \ + AND rentals.movie_title LIKE '%" + movie_title + "%' \ + AND rentals.check_in IS NOT NULL \ + ORDER BY " + sort_type + ";", function(res) { + callback(res); + }); + }; + +module.exports = Movie; diff --git a/package.json b/package.json new file mode 100644 index 0000000..6dae3d2 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "C3Projects--VideoStoreAPI", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www", + "test": "clear; DB=test mocha --recursive", + "db:schema": "node ./utils/schema", + "db:seed": "node ./utils/seed", + "db:setup": "npm run db:schema; npm run db:seed" + }, + "dependencies": { + "body-parser": "~1.13.2", + "cookie-parser": "~1.3.5", + "debug": "~2.2.0", + "express": "~4.13.1", + "mocha": "^2.3.2", + "jade": "~1.11.0", + "morgan": "~1.6.1", + "serve-favicon": "~2.3.0", + "sqlite3": "^3.1.0", + "supertest": "^1.1.0" + } +} 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/rentals.js b/rentals.js new file mode 100644 index 0000000..2de9b81 --- /dev/null +++ b/rentals.js @@ -0,0 +1,105 @@ +"use-strict"; +var sqlite3 = require('sqlite3').verbose(); +var db_env = process.env.DB || 'development'; + +function Rental() { + this.table_name = "rentals"; +} + +Rental.prototype = require('./database'); + +Rental.prototype.all_rentals = function(callback) { + var newDate = new Date(); + var today = this.formatDate(newDate); + var db = new sqlite3.Database('db/' + db_env + '.db'); + + db.exec("BEGIN; \ + UPDATE rentals SET overdue=1 WHERE due_date < " + today + " \ + AND check_in IS NULL; \ + COMMIT;", function() { + db.all( + "SELECT * FROM rentals", function(err, res) { + if (callback) { callback(res); } + }); + }); + + db.close(); +}; + +Rental.prototype.rental_log = function(movie_title, callback) { + movie_title = movie_title.toLowerCase(); + var capitalize_title = movie_title[0].toUpperCase() + movie_title.substring(1); + this.query("SELECT * FROM rentals WHERE movie_title ='" + capitalize_title + "';", function(res) { + callback(res); + }); +}; + +Rental.prototype.overdue = function(callback) { + var newDate = new Date(); + var today = this.formatDate(newDate); + var db = new sqlite3.Database('db/' + db_env + '.db'); + + db.exec("BEGIN; \ + UPDATE rentals SET overdue=1 WHERE due_date < " + today + " \ + AND check_in IS NULL; \ + COMMIT;", function() { + db.all( + "SELECT customers.id, customers.name, customers.registered_at, \ + customers.address, customers.city, customers.state, \ + customers.postal_code, customers.phone, customers.account_credit \ + FROM customers, rentals \ + WHERE customers.id=rentals.customer_id \ + AND rentals.overdue=1 AND rentals.check_in IS NULL;", function(err, res) { + if (callback) { callback(res); } + }); + }); + + db.close(); +}; + +Rental.prototype.check_out = function(data, callback) { +// passing req.body to data + // data will be an object with a key value pair with each item for rental + var check_out_date = new Date(); + var check_out = this.formatDate(check_out_date); + var due_date = new Date(check_out_date); + due_date.setDate(check_out_date.getDate() + 3); + var due = this.formatDate(due_date); + var title = data.movie_title; + var customer_id = data.customer_id; + + var db = new sqlite3.Database('db/' + db_env + '.db'); + db.exec( + "BEGIN; \ + INSERT INTO " + this.table_name + "(check_out, check_in, due_date, overdue, movie_title, customer_id) \ + VALUES(" + check_out + ", null, " + due + ", 0, '" + title + "', " + customer_id + "); \ + UPDATE movies SET inventory_available=inventory_available - 1 WHERE title='" + title + "'; \ + UPDATE customers SET account_credit=account_credit - 3 WHERE id=" + customer_id + "; \ + COMMIT;", function(err) { + if(callback) { callback(err); } + db.close(); + }); +}; + +Rental.prototype.check_in = function(data, callback) { +// data will include movie_title and customer_id + var check_in_date = new Date(); + var check_in = this.formatDate(check_in_date); + var title = data.movie_title; + var customer_id = data.customer_id; + + var db = new sqlite3.Database('db/' + db_env + '.db'); + db.exec( + // update rental: check_in_date and overdue + // update movie: inventory_available + "BEGIN; \ + UPDATE rentals SET check_in=" + check_in + ", overdue=0 WHERE movie_title='" + title + "'; \ + UPDATE movies SET inventory_available=inventory_available + 1 WHERE title='" + title + "'; \ + COMMIT;", function(err) { + if(callback) { callback(err); } + db.close(); + }); +}; + + +module.exports = Rental; diff --git a/routes/customers.js b/routes/customers.js new file mode 100644 index 0000000..9e9fffd --- /dev/null +++ b/routes/customers.js @@ -0,0 +1,30 @@ +var express = require('express'); +var router = express.Router(); +var customer_exports = require('../controllers/customers'); + +router.get('/', function(req, res, next) { + return customer_exports.customersController.all(req, res); +}); + +router.get('/registered_at_sort/:records_per_page/:offset', function(req, res, next) { + return customer_exports.customersController.registered_at_sort(req, res); +}); + +router.get('/name_sort/:records_per_page/:offset', function(req, res, next) { + return customer_exports.customersController.name_sort(req, res); +}); + +router.get('/postal_code_sort/:records_per_page/:offset', function(req, res, next) { + return customer_exports.customersController.postal_code_sort(req, res); +}); + +router.get('/:id/current_rentals', function(req, res, next){ + return customer_exports.customersController.current_rentals(req, res); +}); + +router.get('/:id/past_rentals', function(req, res, next){ + return customer_exports.customersController.past_rentals(req, res); +}); + + +module.exports = router; diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..ecca96a --- /dev/null +++ b/routes/index.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); + +/* GET home page. */ +router.get('/', function(req, res, next) { + res.render('index', { title: 'Express' }); +}); + +module.exports = router; diff --git a/routes/movies.js b/routes/movies.js new file mode 100644 index 0000000..d061ae3 --- /dev/null +++ b/routes/movies.js @@ -0,0 +1,41 @@ +var express = require('express'); +var router = express.Router(); +var movie_exports = require('../controllers/movies'); + +router.get('/', function(req, res, next) { + return movie_exports.moviesController.all(req, res); +}); + +router.get('/release_date_sort/:records_per_page/:offset', function(req, res, next){ + return movie_exports.moviesController.release_date_sort(req, res); +}); + +router.get('/title_sort/:records_per_page/:offset', function(req, res, next){ + return movie_exports.moviesController.title_sort(req, res); +}); + +router.get('/:title', function(req, res, next) { + return movie_exports.moviesController.movie_info(req, res); +}); + +router.get('/:title/current_customers', function(req, res, next) { + return movie_exports.moviesController.current_customers(req, res); +}); + +router.get('/:title/past_customers', function(req, res, next) { + return movie_exports.moviesController.past_customers(req, res); +}); + +router.get('/:title/past_customers/customer_id_sort', function(req, res, next) { + return movie_exports.moviesController.past_customers_id_sort(req, res); +}); + +router.get('/:title/past_customers/customer_name_sort', function(req, res, next) { + return movie_exports.moviesController.past_customers_name_sort(req, res); +}); + +router.get('/:title/past_customers/checkout_date_sort', function(req, res, next) { + return movie_exports.moviesController.past_customers_checkout_date_sort(req, res); +}); + +module.exports = router; diff --git a/routes/rentals.js b/routes/rentals.js new file mode 100644 index 0000000..57eab65 --- /dev/null +++ b/routes/rentals.js @@ -0,0 +1,37 @@ +var express = require('express'); +var router = express.Router(); +var rental_exports = require('../controllers/rentals'); + +router.get('/', function(req, res, next) { + return rental_exports.rentalsController.all_rentals(req, res); +}); + +router.get('/:movie_title/current_customers', function(req, res, next) { + return rental_exports.rentalsController.current_customers(req, res); +}); + +router.get('/:movie_title/rental_log', function(req, res, next) { + return rental_exports.rentalsController.rental_log(req, res); +}); + +router.get('/overdue', function(req, res, next) { + return rental_exports.rentalsController.overdue(req, res); +}); + +router.get('/check_out', function(req, res, next) { + return rental_exports.rentalsController.check_out(req, res); +}); + +router.post('/check_out', function(req, res, next) { + return rental_exports.rentalsController.check_out(req, res); +}); + +router.get('/check_in', function(req, res, next) { + return rental_exports.rentalsController.check_in(req, res); +}); + +router.post('/check_in', function(req, res, next) { //doesn't work with put + return rental_exports.rentalsController.check_in(req, res); +}); + +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/test/controllers/customers.js b/test/controllers/customers.js new file mode 100644 index 0000000..e3ffaf7 --- /dev/null +++ b/test/controllers/customers.js @@ -0,0 +1,196 @@ +var request = require('supertest'), + assert = require('assert'), + app = require('../../app'), + sqlite3 = require('sqlite3').verbose(), + agent = request.agent(app), + Customer = require('../../customers'), + customer_keys = ['id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit'], + rental_keys = ['id', 'check_out', 'check_in', 'due_date', 'overdue', 'movie_title', 'customer_id']; + +describe("customers controller", function() { + var customer, db_cleaner; + + beforeEach(function(done) { + customer = new Customer(); + + db_cleaner = new sqlite3.Database('db/test.db'); + db_cleaner.serialize(function() { + db_cleaner.exec( + "BEGIN; \ + DELETE FROM rentals; DELETE FROM customers; \ + INSERT INTO rentals(check_out, check_in, due_date, overdue, movie_title, customer_id) \ + VALUES('2015-06-16', '2015-06-17', '2015-06-19', 0, 'Jaws', 1), \ + ('2015-06-16', null, '2015-06-19', 1, 'Alien', 1); \ + INSERT INTO customers(name, registered_at, address, city, state, postal_code, phone, account_credit) \ + VALUES('Harry', 20150616, '1234', 'Seattle', 'WA', '98103', '1234567', 123), \ + ('Hermione', 20150501, '5678', 'London', 'UK', '99999', '1234568', 213); \ + COMMIT;" + , function(err) { + db_cleaner.close(); + done(); + } + ); + }); + }); + + describe("GET '/customers'", function() { + it("knows about the route", function(done) { + agent.get('/customers').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of all the customer objects", function(done) { + agent.get('/customers').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(result.body.length, 2); + + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }); + }); + + describe("GET '/customers/registered_at_sort/:records_per_page/:offset'", function() { + it("knows about the route", function(done) { + agent.get('/customers/registered_at_sort/1/2').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of n customer objects offset by p", function(done) { + agent.get('/customers/registered_at_sort/1/0').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(result.body.length, 1); + + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }); + + it("the returned array is sorted by registered_at field", function(done) { + agent.get('/customers/registered_at_sort/1/0').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(result.body[0].name, "Hermione"); + done(); + }); + }); + }); + + describe("GET /customers/name_sort/:records_per_page/:offset", function() { + it("knows about the route", function(done) { + agent.get("/customers/name_sort/1/0").set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of n customer objects offset by p", function(done) { + agent.get('/customers/name_sort/2/0').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(result.body.length, 2); + + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }); + + it("the returned array is sorted by name field", function(done) { + agent.get('/customers/name_sort/1/0').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(result.body[0].name, "Harry"); + done(); + }); + }); + }); + + describe("GET /customers/postal_code_sort/:records_per_page/:offset", function(done) { + it("knows about the route", function(done) { + agent.get("/customers/postal_code_sort/1/0").set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of n customer objects offset by p", function(done) { + agent.get('/customers/postal_code_sort/2/0').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(result.body.length, 2); + + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }); + + it("the returned array is sorted by postal_code field", function(done) { + agent.get('/customers/postal_code_sort/1/0').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(result.body[0].name, "Harry"); + done(); + }); + }); + }); + + describe("GET /customers/:id/current_rentals", function() { + it("knows about the route", function(done) { + agent.get("/customers/1/current_rentals").set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("retuns an array of the customer with current rentals", function(done) { + agent.get("/customers/1/current_rentals").set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(result.body.length, 1); + assert.equal(result.body[0].movie_title, "Alien"); + + assert.deepEqual(Object.keys(result.body[0]), rental_keys); + done(); + }); + }); + }); + + describe("GET /customers/:id/past_rentals", function() { + it("knows about the route", function(done) { + agent.get("/customers/1/past_rentals").set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("retuns an array of the customer with current rentals", function(done) { + agent.get("/customers/1/past_rentals").set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(result.body.length, 1); + assert.equal(result.body[0].movie_title, "Jaws"); + + assert.deepEqual(Object.keys(result.body[0]), rental_keys); + done(); + }); + }); + }); +}); diff --git a/test/controllers/movies.js b/test/controllers/movies.js new file mode 100644 index 0000000..171e099 --- /dev/null +++ b/test/controllers/movies.js @@ -0,0 +1,287 @@ +var request = require('supertest'), + assert = require('assert'), + app = require('../../app'), + sqlite3 = require('sqlite3').verbose(), + agent = request.agent(app), + Movie = require('../../movies'); + +describe("movies controller", function() { + var movie, db_cleaner; + var movie_keys = ['id', 'title', 'overview', 'release_date', 'inventory', 'inventory_available']; + var customer_keys = ['id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit']; + beforeEach(function(done) { + movie = new Movie(); + + db_cleaner = new sqlite3.Database('db/test.db'); + db_cleaner.serialize(function() { + db_cleaner.exec( + "BEGIN; \ + DELETE FROM movies; DELETE FROM customers; DELETE FROM rentals; \ + INSERT INTO rentals(check_out, check_in, due_date, overdue, movie_title, customer_id) \ + VALUES('2015-06-16', '2015-06-17', '2015-06-19', 0, 'Jaws', 1), \ + ('2015-06-10', '2015-06-12', '2015-06-13', 0, 'Jaws', 2),\ + ('2015-06-16', null, '2015-06-19', 1, 'Alien', 1); \ + INSERT INTO movies(title, overview, release_date, inventory, inventory_available) \ + VALUES('Jaws', 'omg sharks!', '1975-06-19', 6, 6), \ + ('Alien', 'omg aliens!', 1979-05-25, 4, 4); \ + INSERT INTO customers(name, registered_at, address, city, state, postal_code, phone, account_credit) \ + VALUES('Harry', '2015-06-16', '1234', 'Seattle', 'WA', '98103', '1234567', 123),\ + ('Hermione', '2015-06-10', '1234', 'Pasadena', 'CA', '97123', '7654321', 231);\ + COMMIT;" + , function(err) { + db_cleaner.close(); + done(); + } + ); + }); + }); + var movies_path = '/movies'; + describe("GET movies_path", function() { + it("knows about the route", function(done) { + agent.get(movies_path).set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of movie objects", function(done) { + agent.get(movies_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body.length, 2); + + movie_keys; + assert.deepEqual(Object.keys(result.body[0]), movie_keys); + done(); + }); + }); + }); + + var title_sort_path = '/movies/title_sort/1/1'; + describe("GET title_sort_path", function() { + it("knows about the route", function(done) { + agent.get('/movies/title_sort/1/1').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of movie objects 1 per page offset by 2", function(done) { + agent.get(title_sort_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body.length, 1); + movie_keys; + assert.deepEqual(Object.keys(result.body[0]), movie_keys); + done(); + }); + }); + + it("sorts the movies by title", function(done) { + agent.get(title_sort_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body[0].title, 'Jaws'); + movie_keys; + assert.deepEqual(Object.keys(result.body[0]), movie_keys); + done(); + }); + }) + }); + + var release_date_sort_path = '/movies/title_sort/1/1'; + describe("GET release_date_sort_path", function() { + it("knows about the route", function(done) { + agent.get(release_date_sort_path).set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of movie objects 1 per page offset by 2", function(done) { + agent.get(release_date_sort_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body.length, 1); + movie_keys; + assert.deepEqual(Object.keys(result.body[0]), movie_keys); + done(); + }); + }); + + it("sorts the movies by release date", function(done) { + agent.get(release_date_sort_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body[0].title, 'Jaws'); + movie_keys; + assert.deepEqual(Object.keys(result.body[0]), movie_keys); + done(); + }); + }) + }); + + var current_customers_path = '/movies/Alien/current_customers'; + describe("GET current_customers_path", function() { + it("knows about the route", function(done) { + agent.get('/movies/Jaws/current_customers').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of customers who currently have the movie checked out", function(done) { + agent.get(current_customers_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body.length, 1); + customer_keys; + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }); + }); + + var past_customers_path = '/movies/Jaws/past_customers' + describe("GET past_customers_path", function() { + it("knows about the route", function(done) { + agent.get(past_customers_path).set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of customers who have checked the movie out in the past", function(done) { + agent.get('/movies/Jaws/past_customers').set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body.length, 2); + customer_keys; + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }); + }); + + var past_customers_id_sort_path = '/movies/Jaws/past_customers/customer_id_sort' + describe("GET past_customers_id_sort_path", function() { + it("knows about the route", function(done) { + agent.get(past_customers_id_sort_path).set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of customers who have checked the movie out in the past", function(done) { + agent.get(past_customers_id_sort_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body.length, 2); + customer_keys; + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }); + + it("sorts the customers by id", function(done) { + agent.get(past_customers_id_sort_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body[0].id, 1); + customer_keys; + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }) + }); + + var past_customer_name_sort_path = '/movies/Jaws/past_customers/customer_name_sort' + describe("GET past_customer_name_sort_path", function() { + it("knows about the route", function(done) { + agent.get(past_customer_name_sort_path).set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of customers who have checked the movie out in the past", function(done) { + agent.get(past_customer_name_sort_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body.length, 2); + customer_keys; + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }); + + it("sorts the customers by name", function(done) { + agent.get(past_customer_name_sort_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body[0].id, 1); + customer_keys; + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }) + }); + + var past_customers_checkout_sort_path = '/movies/Jaws/past_customers/checkout_date_sort' + describe("GET past_customers_checkout_sort_path", function() { + it("knows about the route", function(done) { + agent.get(past_customers_checkout_sort_path).set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of customers who have checked the movie out in the past", function(done) { + agent.get(past_customers_checkout_sort_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body.length, 2); + customer_keys; + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }); + + it("sorts the customers by name", function(done) { + agent.get(past_customers_checkout_sort_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body[0].id, 2); + customer_keys; + assert.deepEqual(Object.keys(result.body[0]), customer_keys); + done(); + }); + }) + }); + + //:title + describe("GET '/movies/Jaws'", function() { + it("knows about the route", function(done) { + agent.get('/movies/jaws').set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of movie objects", function(done) { + agent.get('/movies/jaws').set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body[0].overview, 'omg sharks!'); + + movie_keys; + assert.deepEqual(Object.keys(result.body[0]), movie_keys); + done(); + }); + }); + }); +}); // top level describe diff --git a/test/controllers/rentals.js b/test/controllers/rentals.js new file mode 100644 index 0000000..2a5e05f --- /dev/null +++ b/test/controllers/rentals.js @@ -0,0 +1,126 @@ +var request = require('supertest'), + assert = require('assert'), + app = require('../../app'), + sqlite3 = require('sqlite3').verbose(), + agent = request.agent(app), + Rental = require('../../rentals'); + +describe("rentals controller", function() { + var rental, db_cleaner; + + beforeEach(function(done) { + rental = new Rental(); + + db_cleaner = new sqlite3.Database('db/test.db'); + db_cleaner.serialize(function() { + db_cleaner.exec( + "BEGIN; \ + DELETE FROM rentals; DELETE FROM customers; \ + INSERT INTO rentals(check_out, check_in, due_date, overdue, movie_title, customer_id) \ + VALUES(20150616, 20150617, 20150619, 0, 'Jaws', 1), \ + (20150616, null, 20150619, 1, 'Alien', 1); \ + INSERT INTO customers(name, registered_at, address, city, state, postal_code, phone, account_credit) \ + VALUES('Harry', 20150616, '1234', 'Seattle', 'WA', '98103', '1234567', 123); \ + COMMIT;", function(err) { + db_cleaner.close(); + done(); + } + ); + }); + }); + + var rentals_path = '/rentals'; + describe("GET rentals_path", function() { + it("knows about the route", function(done) { + agent.get(rentals_path).set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of rental objects", function(done) { + agent.get(rentals_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body.length, 2); + + var keys = ['id', 'check_out', 'check_in', 'due_date', 'overdue', 'movie_title', 'customer_id']; + assert.deepEqual(Object.keys(result.body[0]), keys); + done(); + }); + }); + }); + + var rental_log_path = '/rentals/Jaws/rental_log'; + describe("GET rental_log_path", function() { + it("knows about the route", function(done) { + agent.get(rental_log_path).set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of all rentals of that movie title", function(done) { + agent.get(rental_log_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body.length, 1); + + var keys = ['id', 'check_out', 'check_in', 'due_date', 'overdue', 'movie_title', 'customer_id']; + assert.deepEqual(Object.keys(result.body[0]), keys); + done(); + }); + }); + }); + + var rentals_overdue_path = '/rentals/overdue'; + describe("GET rentals_overdue_path", function() { + it("knows about the route", function(done) { + agent.get(rentals_overdue_path).set('Accept', 'application/json') + .expect('Content-Type', /application\/json/) + .expect(200, function(error, result) { + assert.equal(error, undefined); + done(); + }); + }); + + it("returns an array of overdue rental objects", function(done) { + agent.get(rentals_overdue_path).set("Accept", "application/json") + .expect(200, function(error, result) { + assert.equal(result.body.length, 1); + + var keys = ['id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit']; + assert.deepEqual(Object.keys(result.body[0]), keys); + done(); + }); + }); + }); + + var check_out_path = '/rentals/check_out'; + var new_rental = { movie_title: 'Jaws', customer_id: 1}; + describe("POST check_out_path", function(){ + it("creates a new rental record", function(done){ + agent.post(check_out_path).set('Accept', 'application/json') + .send(new_rental) + .expect(200) + .expect(rental.all.length, 3); + done(); + }); + }); + + var check_in_path = '/rentals/check_in'; + var update_rental = { movie_title: 'Alien', customer_id: 1}; + describe("PUT check_in_path", function(){ + it("updates an existing rental record", function(done){ + agent.put(check_in_path).set('Accept', 'application/json') + .send(update_rental) + .expect(200) + .expect("Alien is updated"); + done(); + }); + }); + + +}); //final describe close diff --git a/test/models/database.js b/test/models/database.js new file mode 100644 index 0000000..0051f74 --- /dev/null +++ b/test/models/database.js @@ -0,0 +1,61 @@ +var assert = require('assert'), + Database = require('../../database'), + Movie = require('../../movies'), + Customer = require('../../customers'), + Rental = require('../../rentals'), + sqlite3 = require('sqlite3').verbose(); + +describe("Database", function() { + var movie, customer, rental, db_cleaner; + + beforeEach(function(done) { + movie = new Movie(); + customer = new Customer(); + rental = new Rental(); + + + db_cleaner = new sqlite3.Database('db/test.db'); + db_cleaner.serialize(function() { + db_cleaner.exec( + "BEGIN; \ + DELETE FROM rentals; DELETE FROM customers; DELETE FROM movies; \ + INSERT INTO rentals(check_out, check_in, due_date, overdue, movie_title, customer_id) \ + VALUES(20150616, 20150617, 20150619, 0, 'Jaws', 1), \ + (20150616, null, 20150619, 1, 'Alien', 1); \ + INSERT INTO customers(name, registered_at, address, city, state, postal_code, phone, account_credit) \ + VALUES('Harry', 20150616, '1234', 'Seattle', 'WA', '98103', '1234567', 123); \ + INSERT INTO movies(title, overview, release_date, inventory, inventory_available) \ + VALUES('Jaws', 'something', 19750619, 6, 6), \ + ('Alien', 'something else', 19790525, 4, 4); \ + COMMIT;", function(err) { + db_cleaner.close(); + done(); + } + ); + }); + }); + + describe("models that inherit from database", function() { + it("Movie can be instantiated", function(done) { + assert(movie instanceof Movie); + done(); + }); + + it("Customer can be instantiated", function(done) { + assert(customer instanceof Customer); + done(); + }); + + it("Rental can be instantiated", function(done) { + assert(rental instanceof Rental); + done(); + }); + }); + + // describe("formatDate", function() { + // it("returns date as an integer in the form of YYYYMMDD", function(done) { + // Database.formatDate(); + // }); + // }); + +}); diff --git a/customers.json b/utils/customers.json similarity index 100% rename from customers.json rename to utils/customers.json diff --git a/movies.json b/utils/movies.json similarity index 100% rename from movies.json rename to utils/movies.json diff --git a/utils/rentals.json b/utils/rentals.json new file mode 100644 index 0000000..46fc5a5 --- /dev/null +++ b/utils/rentals.json @@ -0,0 +1,26 @@ +[ + { + "check_out": 20150616, + "check_in": null, + "due_date": 20150619, + "overdue": 0, + "customer_id": 1, + "movie_title": "Jaws" + }, + { + "check_out": 20150616, + "check_in": 20150618, + "due_date": 20150619, + "overdue": 0, + "customer_id": 2, + "movie_title": "Alien" + }, + { + "check_out": 20150616, + "check_in": null, + "due_date": 20150619, + "overdue": 0, + "customer_id": 3, + "movie_title": "The Birds" + } +] diff --git a/utils/schema.js b/utils/schema.js new file mode 100644 index 0000000..8c69d5c --- /dev/null +++ b/utils/schema.js @@ -0,0 +1,81 @@ +"use-strict"; + +var sqlite3 = require('sqlite3').verbose(), + db_env = process.env.DB || 'development', + db = new sqlite3.Database('db/' + db_env + '.db'); + +var movie_fields = [ + ['title', 'text'], + ['overview', 'text'], + ['release_date', 'text'], + ['inventory', 'integer'], + ['inventory_available', 'integer'] +] + +var customer_fields = [ + ['name', 'text'], + ['registered_at', 'integer'], + ['address', 'text'], + ['city', 'text'], + ['state', 'text'], + ['postal_code', 'text'], + ['phone', 'text'], + ['account_credit', 'float'] +] + +var rental_fields = [ + ['check_out', 'integer'], + ['check_in', 'integer'], + ['due_date', 'integer'], + ['overdue', 'integer', 'DEFAULT 0'], // 0 for false 1 for true + ['movie_title', 'string'], + ['customer_id', 'integer'] +] + +// I want these to work somewhat how rake db:reset works, so I need to do three things: +// db.serialize will make sure that these things happen in order (otherwise +// they would execute asynchronously) +db.serialize(function() { + // 1. drop existing tables (run means, do this right now!) + db.run("DROP TABLE IF EXISTS movies;"); + db.run("DROP TABLE IF EXISTS customers;"); + db.run("DROP TABLE IF EXISTS rentals;"); + + // 2. create fresh versions of those tables + db.run("CREATE TABLE movies (id INTEGER PRIMARY KEY);"); + db.run("CREATE TABLE customers (id INTEGER PRIMARY KEY);"); + db.run("CREATE TABLE rentals (id INTEGER PRIMARY KEY);"); + // FOREIGN KEY (customer_id) REFERENCES customer(id), \ + // FOREIGN KEY (movie_id) REFERENCES movie(id));"); + + + // 3. add the columns to those tables + // CREATE MOVIES TABLE COLUMNS + for(var i = 0; i < movie_fields.length; i++) { + var movie_name = movie_fields[i][0], + movie_type = movie_fields[i][1]; + + db.run("ALTER TABLE movies ADD COLUMN " + movie_name + " " + movie_type + ";"); + } + + // CREATE CUSTOMERS TABLE COLUMNS + for(var l = 0; l < customer_fields.length; l++) { + var customer_name = customer_fields[l][0], + customer_type = customer_fields[l][1]; + + db.run("ALTER TABLE customers ADD COLUMN " + customer_name + " " + customer_type + ";"); + } + + // CREATE RENTALS TABLE COLUMNS + for(var k = 0; k < rental_fields.length; k++) { + var rental_name = rental_fields[k][0], + rental_type = rental_fields[k][1]; + default_value = (rental_fields[k][2] === undefined) ? "" : rental_fields[k][2]; + + + db.run("ALTER TABLE rentals ADD COLUMN " + + rental_name + " " + rental_type + " " + default_value + ";"); + } +}); + +db.close(); diff --git a/utils/seed.js b/utils/seed.js new file mode 100644 index 0000000..291cdc1 --- /dev/null +++ b/utils/seed.js @@ -0,0 +1,100 @@ +"use-strict"; + +var sqlite3 = require('sqlite3').verbose(), + db_env = process.env.DB || 'development', + db = new sqlite3.Database('db/' + db_env + '.db'); + +var movies = require('./movies'); // requires in movies.json file +var movie_statement = db.prepare( // we will use this statement later + "INSERT INTO MOVIES(title, overview, release_date, inventory, inventory_available) \ + VALUES( ?, ?, ?, ?, ?);" +); + +var customers = require('./customers'); // requires in movies.json file +var customer_statement = db.prepare( // we will use this statement later + "INSERT INTO CUSTOMERS(name, registered_at, address, city, state, postal_code, phone, account_credit) \ + VALUES( ?, ?, ?, ?, ?, ?, ?, ?);" +); + +var rentals = require('./rentals'); // requires in movies.json file +var rental_statement = db.prepare( // we will use this statement later + "INSERT INTO RENTALS(check_out, check_in, due_date, overdue, customer_id, movie_title) \ + VALUES( ?, ?, ?, ?, ?, ?);" +); + +var formatDate = function(date) { + var dateObj = new Date(date); + var month = (dateObj.getUTCMonth() + 1).toString(); //months from 1-12 + var day = (dateObj.getUTCDate()).toString(); + var year = (dateObj.getUTCFullYear()).toString(); + + if (month.length == 1) { // This will ensure month is two digits + month = "0" + month; + } + + if (day.length == 1) { // This will ensure day is two digits + day = "0" + day; + } + + return parseInt(year + month + day); +} + +db.serialize(function() { + // loop through movies + for(var i = 0; i < movies.length; i++) { + var movie = movies[i]; + + + var formatted_date = formatDate(movie.release_date); + + // insert each movie into the db + movie_statement.run( + movie.title, + movie.overview, + movie.release_date, + movie.inventory, + movie.inventory // this seeds our inventory_available to be equal to our total inventory + ); + } + + // loop through customers + for(var j = 0; j < customers.length; j++) { + var customer = customers[j]; + // this will format dates in sqlite to read year/month/day for easier sorting + + var formatted_date = formatDate(customer.registered_at); + + // insert each customer into the db + customer_statement.run( + customer.name, + formatted_date, + customer.address, + customer.city, + customer.state, + customer.postal_code, + customer.phone, + customer.account_credit + ); + } + + // loop through rentals + for(var k = 0; k < rentals.length; k++) { + var rental = rentals[k]; + + // insert each rental into the db + rental_statement.run( + rental.check_out, + rental.check_in, + rental.due_date, + rental.overdue, + rental.customer_id, + rental.movie_title + ); + } + + movie_statement.finalize(); + customer_statement.finalize(); + rental_statement.finalize(); +}); + +db.close(); diff --git a/views/error.jade b/views/error.jade new file mode 100644 index 0000000..51ec12c --- /dev/null +++ b/views/error.jade @@ -0,0 +1,6 @@ +extends layout + +block content + h1= message + h2= error.status + pre #{error.stack} diff --git a/views/index.jade b/views/index.jade new file mode 100644 index 0000000..3d63b9a --- /dev/null +++ b/views/index.jade @@ -0,0 +1,5 @@ +extends layout + +block content + h1= title + p Welcome to #{title} diff --git a/views/layout.jade b/views/layout.jade new file mode 100644 index 0000000..15af079 --- /dev/null +++ b/views/layout.jade @@ -0,0 +1,7 @@ +doctype html +html + head + title= title + link(rel='stylesheet', href='/stylesheets/style.css') + body + block content