From 45b942aa42c279f1e2398b00daf5b014fa71221a Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 17 Sep 2015 13:19:20 -0700 Subject: [PATCH 01/72] Added node_modules and db to gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index e43b0f9..2765dfb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .DS_Store +node_modules/ +db/ From f58c0162931a1ba5fb3955e4eb0de9f969767244 Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 17 Sep 2015 13:28:11 -0700 Subject: [PATCH 02/72] first npm install. --- app.js | 60 ++++++++++++++++++++++++ bin/www | 90 ++++++++++++++++++++++++++++++++++++ package.json | 17 +++++++ public/stylesheets/style.css | 8 ++++ routes/index.js | 9 ++++ routes/users.js | 9 ++++ views/error.jade | 6 +++ views/index.jade | 5 ++ views/layout.jade | 7 +++ 9 files changed, 211 insertions(+) create mode 100644 app.js create mode 100755 bin/www create mode 100644 package.json create mode 100644 public/stylesheets/style.css create mode 100644 routes/index.js create mode 100644 routes/users.js create mode 100644 views/error.jade create mode 100644 views/index.jade create mode 100644 views/layout.jade diff --git a/app.js b/app.js new file mode 100644 index 0000000..80a3c36 --- /dev/null +++ b/app.js @@ -0,0 +1,60 @@ +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 routes = require('./routes/index'); +var users = require('./routes/users'); + +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'))); + +app.use('/', routes); +app.use('/users', users); + +// 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/package.json b/package.json new file mode 100644 index 0000000..0ab806b --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "C3Projects--VideoStoreAPI", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www" + }, + "dependencies": { + "body-parser": "~1.13.2", + "cookie-parser": "~1.3.5", + "debug": "~2.2.0", + "express": "~4.13.1", + "jade": "~1.11.0", + "morgan": "~1.6.1", + "serve-favicon": "~2.3.0" + } +} \ No newline at end of file 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..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/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/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 From 81efc00890f02d97d88b61b55d3505f409a9c4d0 Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 17 Sep 2015 13:35:17 -0700 Subject: [PATCH 03/72] Added more boilerplate directories for db and utils. Moved seeds into utils folder --- app.js | 6 +++--- customers.json => utils/customers.json | 0 movies.json => utils/movies.json | 0 utils/schema.js | 0 utils/seeds.js | 0 5 files changed, 3 insertions(+), 3 deletions(-) rename customers.json => utils/customers.json (100%) rename movies.json => utils/movies.json (100%) create mode 100644 utils/schema.js create mode 100644 utils/seeds.js diff --git a/app.js b/app.js index 80a3c36..eae8d6c 100644 --- a/app.js +++ b/app.js @@ -5,9 +5,6 @@ var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); -var routes = require('./routes/index'); -var users = require('./routes/users'); - var app = express(); // view engine setup @@ -22,7 +19,10 @@ app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); +var routes = require('./routes/index'); app.use('/', routes); + +var users = require('./routes/users'); app.use('/users', users); // catch 404 and forward to error handler 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/schema.js b/utils/schema.js new file mode 100644 index 0000000..e69de29 diff --git a/utils/seeds.js b/utils/seeds.js new file mode 100644 index 0000000..e69de29 From 03f48df3f4c147fd24b8ab0e73c3833410bf4864 Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 17 Sep 2015 13:58:55 -0700 Subject: [PATCH 04/72] Created database connection with a StoreDatabase object and a .query property. --- database.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 database.js diff --git a/database.js b/database.js new file mode 100644 index 0000000..33f8350 --- /dev/null +++ b/database.js @@ -0,0 +1,23 @@ +"use strict"; + +var sqlite3 = require('sqlite3').verbose(); + +function StoreDatabase(path) { + this.path = path; +} + +StoreDatabase.prototype = { + query: function(statement, callback) { + var db = new sqlite3.Database(this.path); // creates a connection to the db + + db.serialize(function() { + db.all(statement, function(err, res) { // statement == some SQL string + if (callback) { callback(res); } // we only get a callback if it's successful + }); + }); + + db.close(); + } +}; + +module.exports = StoreDatabase; \ No newline at end of file From ae4831a98e7f480ad045e8823c4d3333ed1631d8 Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 17 Sep 2015 14:19:31 -0700 Subject: [PATCH 05/72] Created schema file which will drop, reset and migrate our db tables/columns. --- package.json | 4 ++- utils/schema.js | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 0ab806b..09a35e5 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,9 @@ "version": "0.0.0", "private": true, "scripts": { - "start": "node ./bin/www" + "start": "node ./bin/www", + "reset": "node ./utils/schema.js", + "seed": "node ./utils/seeds.js" }, "dependencies": { "body-parser": "~1.13.2", diff --git a/utils/schema.js b/utils/schema.js index e69de29..a408fee 100644 --- a/utils/schema.js +++ b/utils/schema.js @@ -0,0 +1,72 @@ +"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_total', 'integer'], + ['inventory_avail', 'integer'] +] + +var customer_fields = [ + ['name', 'text'], + ['registered_at', 'text'], + ['address', 'text'], + ['city', 'text'], + ['state', 'text'], + ['postal_code', 'text'], + ['phone', 'text'], + ['account_credit', 'text'] +] + +var rental_fields = [ + ['customer_id', 'integer'], + ['movie_id', 'integer'], + ['checkout_date', 'text'], + ['due_date', 'text'], + ['return_date', 'text'] +] + +db.serialize(function() { + // drop existing tables + db.run("DROP TABLE IF EXISTS movies;"); + db.run("DROP TABLE IF EXISTS customers;"); + db.run("DROP TABLE IF EXISTS rentals;"); + + // create fresh versions of 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);"); + + // add columns to movies tables + for(var i = 0; i < movie_fields.length; i++) { + var name = movie_fields[i][0], + type = movie_fields[i][1]; + + db.run("ALTER TABLE movies ADD COLUMN " + name + " " + type + ";"); + } + + // add columns to customers table + for(var i = 0; i < customer_fields.length; i++) { + var name = customer_fields[i][0], + type = customer_fields[i][1]; + + db.run("ALTER TABLE customers ADD COLUMN " + name + " " + type + ";"); + } + + // add columns to rentals table + for(var i = 0; i < rental_fields.length; i++) { + var name = rental_fields[i][0], + type = rental_fields[i][1]; + + db.run("ALTER TABLE rentals ADD COLUMN " + name + " " + type + ";"); + } + +}); + +db.close(); + From ce0e282841f25c305ee25e217cae1a5a1c7c83d6 Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 17 Sep 2015 14:45:46 -0700 Subject: [PATCH 06/72] Wrote tests for database.js file --- test/database_tests.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/database_tests.js diff --git a/test/database_tests.js b/test/database_tests.js new file mode 100644 index 0000000..a2718a2 --- /dev/null +++ b/test/database_tests.js @@ -0,0 +1,41 @@ +var assert = require("assert"); +var Database = require("../database"); // our database.js file + +describe("Database", function() { + var db; + var database_path = "db/test.db"; + + beforeEach(function() { + db = new Database(database_path); + }); + + it("can be instantiated", function() { + assert.equal(db instanceof Database, true); + }); + + it("has a 'query' property that is a function", function() { + assert.equal(typeof db.query, "function"); + }); + + it("holds onto the 'path' to the database", function() { + assert.equal(db.path, database_path); + }); + + describe("'query' function", function() { + before(function() { + // create a customers table + db.query("CREATE TABLE IF NOT EXISTS customers (name TEXT);"); + + // insert some customers + }); + + it("has a customers table", function(done) { + var table_exists = "SELECT count(*) AS table_count FROM sqlite_master WHERE type='table' AND name='customers'; "; + + db.query(table_exists, function(result) { + assert.equal(result[0].table_count, 1); + done(); + }); + }); + }); +}); \ No newline at end of file From 7e688b6f86dabcee12b2698ff50539ea1f4932bf Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 17 Sep 2015 14:58:38 -0700 Subject: [PATCH 07/72] Wrote SQL statements and db.serialize loops to seed our db with movies and customers --- utils/seeds.js | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/utils/seeds.js b/utils/seeds.js index e69de29..ed4745b 100644 --- a/utils/seeds.js +++ b/utils/seeds.js @@ -0,0 +1,64 @@ +"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'); +var movie_statement = db.prepare( + "INSERT INTO movies(title, overview, release_date, inventory_total, inventory_avail) \ + VALUES (?, ?, ?, ?, ?);" +); + +var customers = require('./customers'); +var customer_statement = db.prepare( + "INSERT INTO customers(name, registered_at, address, city, state, postal_code, phone, account_credit) \ + VALUES (?, ?, ?, ?, ?, ?, ?, ?);" +); + +// var movies = require('./movies'); +// var movie_statement = db.prepare( +// "INSERT INTO movies(title, overview, release_date, inventory_total, inventory_avail) \ +// VALUES (?, ?, ?, ?, ?);" +// ); + +db.serialize(function() { + // loop through movies + for(var i = 0; i < movies.length; i++) { + var movie = movies[i]; + + // insert each into the db + movie_statement.run( + movie.title, + movie.overview, + movie.release_date, + movie.inventory, + movie.inventory + ); + } + + movie_statement.finalize(); + + // loop through customers + for(var i = 0; i < customers.length; i++) { + var customer = customers[i]; + + // insert each into the db + customer_statement.run( + customer.name, + customer.registered_at, + customer.address, + customer.city, + customer.state, + customer.postal_code, + customer.phone, + customer.account_credit + ); + } + + customer_statement.finalize(); + +}); + +db.close(); + From 57f8b530e7dc59948a802b29e12d18de6944bb43 Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 17 Sep 2015 15:36:09 -0700 Subject: [PATCH 08/72] Added md file to explain our endpoints. Lots of notes right now. Will clean up later for final production. --- endpoints.md | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 endpoints.md diff --git a/endpoints.md b/endpoints.md new file mode 100644 index 0000000..7e92a67 --- /dev/null +++ b/endpoints.md @@ -0,0 +1,111 @@ +VIDEO STORE PROJECT ROUTES ***************** + + CUSTOMER + + GET '/customers' + returns all of the customers + all of the attr of customers + + GET '/customers&order_by="name"' + returns n number of customers (hardcoded?) sorted by name + offset by p records (hardcoded) + all of the attr of customers + + GET '/customers&order_by="registered_at"' + returns n number of customers (hardcoded?) sorted by registered_at + offset by p records (hardcoded) + all of the attr of customers + + GET '/customers&order_by="postal_code"' + returns n number of customers (hardcoded?) sorted by postal_code + offset by p records (hardcoded) + all of the attr of customers + + GET '/customers/:id' + all of the attr of that customer + + currently checked out movies + all movies with that customer_id and return_date == nil + include id, title + + movies checked out in the past + all movies with that customer_id and return_date != nil (sort ASC by checkout_date) + include id, title and return_date + + MOVIES + + GET '/movies' + returns all of the movies + all of the attr of movies + + GET '/movies&order_by="title"' + returns n number of movies (hardcoded?) sorted by title + offset by p records (hardcoded) + + GET '/movies&order_by="release_date"' + returns n number of movies (hardcoded?) sorted by release_date + offset by p records (hardcoded) + + GET '/movies/:title' returns movies that match the title query + returns movie synopsis, release_date, inventory_total, inventory_avail + + GET '/movies/:title/customers' default is sorting by id + GET '/movies/:title/customers&order_by="name"' + GET '/movies/:title/customers&order_by="checkout_date"' + { current_customers: + [ customer1 : { name: blah, ... }, + customer2: { etc } ], customers CURRENTLY checked out this movie + + previous_customers: + [customers PREVIOUSLY who checked out this movie] + } + + RENTALS-- Checkout ******* + + POST '/customers/:id/rental/:title' + maybe change it be searching for movie id instead of movie title? + + creates new rental entry + customer_id, movie_id, checkout_date, due_date of +7 days later, return_date == nil + on success... + + PUT updates inventory_avail -1 for that movie + updates customer account_credit -$X rental fee + + RENTALS-- Checkin ******* + + PUT '/customers/:id/rental/:title' + updates return_date to Time.now (rental record) + updates inventory_avail +1 for that movie + + GET '/rentals/overdue' + array of customers with all their overdue movies + overdue = current_date > due_date && return_date == nil + + { customers: [ + { name1 : "something", + overdue_movies: [ + { title1 : "", + release_date : dateTime, + }, + { title2 : "", + release_date : dateTime, + } + ] + }, + + { name2 : "something", + overdue_movies: [ + { title1 : "", + release_date : dateTime, + }, + { title2 : "", + release_date : dateTime, + } + ] + }, + ] + } + + + ************************** \ No newline at end of file From 8aa78aec9b7c20b13608477b088f4f7a79c9682f Mon Sep 17 00:00:00 2001 From: amirahaile Date: Thu, 17 Sep 2015 16:19:10 -0700 Subject: [PATCH 09/72] Started documentation for our endpoints. --- endpoints.md | 218 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 160 insertions(+), 58 deletions(-) diff --git a/endpoints.md b/endpoints.md index 7e92a67..2b9fc3f 100644 --- a/endpoints.md +++ b/endpoints.md @@ -1,42 +1,118 @@ -VIDEO STORE PROJECT ROUTES ***************** +# Video Store Project Routes +The following are all the endpoints available from our Video Store API. + +## Customer + +__Endpoint__ +`GET ./customers` +Returns all the information on record of all of our customers. + +__Request Parameters__ + +| Query Parameter | Value | +| :-------------------| :------------- | +| `order_by ` | _Optional._ Provide this parameter if you would like the customers sorted. Options include: `name`, `registered_at`, or `postal_code`. | + +__Response Format__ + + { + "customers" : [ + { + "id": 1, + "name": "Shelley Rocha", + "registered_at": "Wed, 29 Apr 2015 07:54:14 -0700", + "address": "Ap #292-5216 Ipsum Rd.", + "city": "Hillsboro", + "state": "OR", + "postal_code": "24309", + "phone": "(322) 510-8695", + "account_credit": 13.15 + }, + { + "id": "2", + "name": "Curran Stout", + "registered_at": "Wed, 16 Apr 2014 21:40:20 -0700", + "address": "Ap #658-1540 Erat Rd.", + "city": "San Francisco", + "state": "California", + "postal_code": "94267", + "phone": "(908) 949-6758", + "account_credit": 35.66 + } + … + ] + } - CUSTOMER + returns n number of customers (hardcoded?) sorted by name + offset by p records (hardcoded) + all of the attr of customers - GET '/customers' - returns all of the customers - all of the attr of customers +*** - GET '/customers&order_by="name"' - returns n number of customers (hardcoded?) sorted by name - offset by p records (hardcoded) - all of the attr of customers +__Endpoint__ +`GET /customers/{:id}` + all of the attr of that customer + currently checked out movies + all movies with that customer_id and return_date == nil + include id, title - GET '/customers&order_by="registered_at"' - returns n number of customers (hardcoded?) sorted by registered_at - offset by p records (hardcoded) - all of the attr of customers + movies checked out in the past + all movies with that customer_id and return_date != nil (sort ASC by checkout_date) + include id, title and return_date - GET '/customers&order_by="postal_code"' - returns n number of customers (hardcoded?) sorted by postal_code - offset by p records (hardcoded) - all of the attr of customers +__Request Parameter__ + + | Path Parameter | Value | + | :---------------| :----------------- | + | `id ` | The customer's ID. | + +__Response__ + + { + "customer": { + "renting": [ + { + "id": 1 + "title": "Psycho", + "checkout_date": "", + "due_date": "" , + "return_date": null + }, + { + "id": 2 + "title": "Jaws", + "checkout_date": "", + "due_date": "", + "return_date": null + } + ], + "rented" : [ + { + "id": 8 + "title": "The French Connection", + "checkout_date": "", + "due_date": "", + "return_date": "" + } + ] + } + } - GET '/customers/:id' - all of the attr of that customer - currently checked out movies - all movies with that customer_id and return_date == nil - include id, title +## MOVIES - movies checked out in the past - all movies with that customer_id and return_date != nil (sort ASC by checkout_date) - include id, title and return_date +__Endpoint__ +`GET ./movies` +Returns all of the movies in our database with their complete information. - MOVIES +__Request Parameters__ + +| Query Parameter | Value | +| :-------------------| :------------- | +| `order_by` | _Optional._ Provide this parameter if you would like the customers sorted. Options include: `title` or `release_date`. | + +__Response__ - GET '/movies' - returns all of the movies - all of the attr of movies GET '/movies&order_by="title"' returns n number of movies (hardcoded?) sorted by title @@ -46,41 +122,70 @@ VIDEO STORE PROJECT ROUTES ***************** returns n number of movies (hardcoded?) sorted by release_date offset by p records (hardcoded) - GET '/movies/:title' returns movies that match the title query - returns movie synopsis, release_date, inventory_total, inventory_avail +*** + +__Endpoint__ +`GET ./movies/{:title}` +Returns movies that match the title query. + +__Request Parameters__ - GET '/movies/:title/customers' default is sorting by id - GET '/movies/:title/customers&order_by="name"' - GET '/movies/:title/customers&order_by="checkout_date"' - { current_customers: - [ customer1 : { name: blah, ... }, - customer2: { etc } ], customers CURRENTLY checked out this movie +| Path Parameter | Value | +| :------------------| :------------- | +| `title` | The title of the movie. | - previous_customers: - [customers PREVIOUSLY who checked out this movie] +__Response__ + + { + "movies" : [ + { + "title": "The Night of the Hunter", + "overview": "Harry Powell marries and murders widows for their money, believing he is helping God do away with women who arouse men's carnal instincts. Arrested for auto theft, he shares a cell with condemned killer Ben Harper and tries to get him to reveal the whereabouts of the $10,000 he stole. Only Ben's nine-year-old son, John, and four-year-old daughter, Pearl, know the money is in Pearl's doll; and they have sworn to their father to keep this secret. After Ben is executed, Preacher goes to Cresap's Landing to court Ben's widow, Willa. When he overwhelms her with his Scripture quoting, sermons, and hymns, she agrees to marry him. On their wedding night, he tells her they will never have sex because it is sinful.", + "release_date": "1955-07-26", + "inventory": 9 + }, + { + "title": "Night of the Living Dead", + "overview": "A group of people try to survive an attack of bloodthirsty zombies while trapped in a rural Pennsylvania farmhouse. Although not the first zombie film, Night of the Living Dead is the progenitor of the contemporary \"zombie apocalypse\" horror film, and it greatly influenced the modern pop-culture zombie archetype.", + "release_date": "1968-10-01", + "inventory": 9 + }, + ] } - RENTALS-- Checkout ******* +GET '/movies/:title/customers' default is sorting by id +GET '/movies/:title/customers&order_by="name"' +GET '/movies/:title/customers&order_by="checkout_date"' + { current_customers: + [ customer1 : { name: blah, ... }, + customer2: { etc } ], customers CURRENTLY checked out this movie + + previous_customers: + [customers PREVIOUSLY who checked out this movie] + } + +## RENTALS - POST '/customers/:id/rental/:title' - maybe change it be searching for movie id instead of movie title? +__Endpoint__ +`POST /customers/{:id}/rental/{:title}` + maybe change it be searching for movie id instead of movie title? - creates new rental entry - customer_id, movie_id, checkout_date, due_date of +7 days later, return_date == nil - on success... + creates new rental entry + customer_id, movie_id, checkout_date, due_date of +7 days later, return_date == nil + on success... - PUT updates inventory_avail -1 for that movie - updates customer account_credit -$X rental fee + PUT updates inventory_avail -1 for that movie + updates customer account_credit -$X rental fee - RENTALS-- Checkin ******* +RENTALS-- Checkin ******* - PUT '/customers/:id/rental/:title' - updates return_date to Time.now (rental record) - updates inventory_avail +1 for that movie +PUT '/customers/:id/rental/:title' + updates return_date to Time.now (rental record) + updates inventory_avail +1 for that movie - GET '/rentals/overdue' - array of customers with all their overdue movies - overdue = current_date > due_date && return_date == nil +GET '/rentals/overdue' + array of customers with all their overdue movies + overdue = current_date > due_date && return_date == nil { customers: [ { name1 : "something", @@ -93,7 +198,7 @@ VIDEO STORE PROJECT ROUTES ***************** } ] }, - + { name2 : "something", overdue_movies: [ { title1 : "", @@ -106,6 +211,3 @@ VIDEO STORE PROJECT ROUTES ***************** }, ] } - - - ************************** \ No newline at end of file From a9ca3358c2644b6efac800024556ef2d1699ccca Mon Sep 17 00:00:00 2001 From: amirahaile Date: Thu, 17 Sep 2015 16:44:23 -0700 Subject: [PATCH 10/72] Saved mocha and sqlite3 as dependencies. --- package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 09a35e5..673e5ed 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,9 @@ "debug": "~2.2.0", "express": "~4.13.1", "jade": "~1.11.0", + "mocha": "^2.3.2", "morgan": "~1.6.1", - "serve-favicon": "~2.3.0" + "serve-favicon": "~2.3.0", + "sqlite3": "^3.1.0" } -} \ No newline at end of file +} From b7644064cbe7f857977ce0746e727caafb8aafaf Mon Sep 17 00:00:00 2001 From: amirahaile Date: Thu, 17 Sep 2015 16:44:44 -0700 Subject: [PATCH 11/72] Renamed the file for our routes. --- routes/customers.js | 17 +++++++++++++++++ routes/users.js | 9 --------- 2 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 routes/customers.js delete mode 100644 routes/users.js diff --git a/routes/customers.js b/routes/customers.js new file mode 100644 index 0000000..e84c52c --- /dev/null +++ b/routes/customers.js @@ -0,0 +1,17 @@ +var express = require('express'); +var router = express.Router(); +var customer_exports = require('../controllers/customers'); + +/* GET customers listing. */ + +// "/customers " +router.get('/', function(req, res, next) { + return customer_exports.customersController.customers(req, res); +}); + +// "/customers/{:id}" +router.get('/:id', function(req, res, next) { + return customer_exports.customersController.customer(req, res); +}); + +module.exports = router; diff --git a/routes/users.js b/routes/users.js deleted file mode 100644 index 623e430..0000000 --- a/routes/users.js +++ /dev/null @@ -1,9 +0,0 @@ -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; From 0cc727a813474f6bb2d38376482374584c7c314a Mon Sep 17 00:00:00 2001 From: amirahaile Date: Thu, 17 Sep 2015 16:46:41 -0700 Subject: [PATCH 12/72] Added semicolons :| --- utils/schema.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/schema.js b/utils/schema.js index a408fee..9c7324e 100644 --- a/utils/schema.js +++ b/utils/schema.js @@ -10,7 +10,7 @@ var movie_fields = [ ['release_date', 'text'], ['inventory_total', 'integer'], ['inventory_avail', 'integer'] -] +]; var customer_fields = [ ['name', 'text'], @@ -21,7 +21,7 @@ var customer_fields = [ ['postal_code', 'text'], ['phone', 'text'], ['account_credit', 'text'] -] +]; var rental_fields = [ ['customer_id', 'integer'], @@ -29,7 +29,7 @@ var rental_fields = [ ['checkout_date', 'text'], ['due_date', 'text'], ['return_date', 'text'] -] +]; db.serialize(function() { // drop existing tables @@ -42,6 +42,7 @@ db.serialize(function() { db.run("CREATE TABLE customers (id INTEGER PRIMARY KEY);"); db.run("CREATE TABLE rentals (id INTEGER PRIMARY KEY);"); + // add columns to movies tables for(var i = 0; i < movie_fields.length; i++) { var name = movie_fields[i][0], @@ -69,4 +70,3 @@ db.serialize(function() { }); db.close(); - From 07a5caeb46b27ee471e4b178a638e2b20a18ecfc Mon Sep 17 00:00:00 2001 From: amirahaile Date: Thu, 17 Sep 2015 17:02:44 -0700 Subject: [PATCH 13/72] Specified db/development.db instead of just db/ --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2765dfb..ef063ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ .DS_Store node_modules/ -db/ +db/development.db From 6bd59e5a5296b3c206c6316bb8fb11951fa9b349 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Thu, 17 Sep 2015 17:03:12 -0700 Subject: [PATCH 14/72] Commented out index route and renamed user to customers. --- app.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app.js b/app.js index eae8d6c..5b087ce 100644 --- a/app.js +++ b/app.js @@ -19,11 +19,12 @@ app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); -var routes = require('./routes/index'); -app.use('/', routes); +// NOTE: Do we even need this…? +// var routes = require('./routes/index'); +// app.use('/', routes); -var users = require('./routes/users'); -app.use('/users', users); +var customers = require('./routes/customers'); +app.use('/customers', customers); // catch 404 and forward to error handler app.use(function(req, res, next) { From 40c272c1bbb10ccff04aeb4394ef369097240fda Mon Sep 17 00:00:00 2001 From: amirahaile Date: Thu, 17 Sep 2015 17:03:29 -0700 Subject: [PATCH 15/72] Formatted comments. --- database.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/database.js b/database.js index 33f8350..b636190 100644 --- a/database.js +++ b/database.js @@ -11,13 +11,15 @@ StoreDatabase.prototype = { var db = new sqlite3.Database(this.path); // creates a connection to the db db.serialize(function() { - db.all(statement, function(err, res) { // statement == some SQL string - if (callback) { callback(res); } // we only get a callback if it's successful + // statement == some SQL string + db.all(statement, function(err, res) { + // we only get a callback if it's successful + if (callback) { callback(res); } }); }); - + db.close(); } }; -module.exports = StoreDatabase; \ No newline at end of file +module.exports = StoreDatabase; From 5cffc738588b12dc4544bf27418d371e63865c79 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Thu, 17 Sep 2015 17:03:48 -0700 Subject: [PATCH 16/72] Created controllers directory and customer controller. --- controllers/customers.js | 53 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 controllers/customers.js diff --git a/controllers/customers.js b/controllers/customers.js new file mode 100644 index 0000000..0166180 --- /dev/null +++ b/controllers/customers.js @@ -0,0 +1,53 @@ +"use strict"; + +var Database = require('../database'); + +exports.customersController = { + + customers: function(req, res) { + var customers = Database.query("SELECT * FROM customers"); + + // loop + var results = { + customers: [] + } + + return res.status(200).json(results); + }, + + customer: function(req, res) { + var results = { + id: , + name: , + registered_at: , + address: , + city: , + state: , + postal_code:, + phone: , + account_credit: + }; + + return res.status(200).json(results); + } + + // database_test: function(req, res) { + // var db = new Database(); + // db.test(); + // + // return res.status(200).send("plain text message"); + // }, + + // zomg: function zomg(req, res) { + // var results = { + // zomg: "zomg it worked!", + // moar: "zomg moar" + // }; + // + // return res.status(200).json(results); + // }, + // + // another_endpoint: function another_endpoint(req, res) { + // return res.status(200).json({ why: "I don't know." }); + // } +}; From a9d033cb3dfc8e42684cbcecbeb182671c1f07e0 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Fri, 18 Sep 2015 09:47:24 -0700 Subject: [PATCH 17/72] Styling and structure for API endpoint documentation. --- endpoints.md | 244 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 175 insertions(+), 69 deletions(-) diff --git a/endpoints.md b/endpoints.md index 2b9fc3f..0d61ceb 100644 --- a/endpoints.md +++ b/endpoints.md @@ -7,6 +7,10 @@ __Endpoint__ `GET ./customers` Returns all the information on record of all of our customers. +returns n number of customers (hardcoded?) sorted by name +offset by p records (hardcoded) + all of the attr of customers + __Request Parameters__ | Query Parameter | Value | @@ -43,10 +47,6 @@ __Response Format__ ] } - returns n number of customers (hardcoded?) sorted by name - offset by p records (hardcoded) - all of the attr of customers - *** __Endpoint__ @@ -99,12 +99,15 @@ __Response__ } -## MOVIES +## Movies __Endpoint__ `GET ./movies` Returns all of the movies in our database with their complete information. +returns n number of movies (hardcoded?) sorted by title +offset by p records (hardcoded) + __Request Parameters__ | Query Parameter | Value | @@ -113,14 +116,11 @@ __Request Parameters__ __Response__ + { + "movies": [ - GET '/movies&order_by="title"' - returns n number of movies (hardcoded?) sorted by title - offset by p records (hardcoded) - - GET '/movies&order_by="release_date"' - returns n number of movies (hardcoded?) sorted by release_date - offset by p records (hardcoded) + ] + } *** @@ -138,76 +138,182 @@ __Response__ { "movies" : [ - { - "title": "The Night of the Hunter", - "overview": "Harry Powell marries and murders widows for their money, believing he is helping God do away with women who arouse men's carnal instincts. Arrested for auto theft, he shares a cell with condemned killer Ben Harper and tries to get him to reveal the whereabouts of the $10,000 he stole. Only Ben's nine-year-old son, John, and four-year-old daughter, Pearl, know the money is in Pearl's doll; and they have sworn to their father to keep this secret. After Ben is executed, Preacher goes to Cresap's Landing to court Ben's widow, Willa. When he overwhelms her with his Scripture quoting, sermons, and hymns, she agrees to marry him. On their wedding night, he tells her they will never have sex because it is sinful.", - "release_date": "1955-07-26", - "inventory": 9 - }, - { - "title": "Night of the Living Dead", - "overview": "A group of people try to survive an attack of bloodthirsty zombies while trapped in a rural Pennsylvania farmhouse. Although not the first zombie film, Night of the Living Dead is the progenitor of the contemporary \"zombie apocalypse\" horror film, and it greatly influenced the modern pop-culture zombie archetype.", - "release_date": "1968-10-01", - "inventory": 9 - }, + { + "title": "The Night of the Hunter", + "overview": "Harry Powell marries and murders widows for their money, believing he is helping God do away with women who arouse men's carnal instincts. Arrested for auto theft, he shares a cell with condemned killer Ben Harper and tries to get him to reveal the whereabouts of the $10,000 he stole. Only Ben's nine-year-old son, John, and four-year-old daughter, Pearl, know the money is in Pearl's doll; and they have sworn to their father to keep this secret. After Ben is executed, Preacher goes to Cresap's Landing to court Ben's widow, Willa. When he overwhelms her with his Scripture quoting, sermons, and hymns, she agrees to marry him. On their wedding night, he tells her they will never have sex because it is sinful.", + "release_date": "1955-07-26", + "inventory": 9 + } ] } -GET '/movies/:title/customers' default is sorting by id -GET '/movies/:title/customers&order_by="name"' -GET '/movies/:title/customers&order_by="checkout_date"' - { current_customers: - [ customer1 : { name: blah, ... }, - customer2: { etc } ], customers CURRENTLY checked out this movie +*** + +__Endpoint__ +`GET /movies/{:title}/customers` +default is sorting by id + +__Request Parameters__ + +| Path Parameter | Value | +| :------------------| :----------------------- | +| `title` | The title of the movie. | + +| Query Parameter | Value | +| :------------------| :----------------------- | +| `order_by` | _Optional._ Provide this parameter if you would like the customers sorted. Options include: `name` or `checkout_date`. | - previous_customers: - [customers PREVIOUSLY who checked out this movie] - } +__Response__ + + { + "current_customers": [ + { + "id": "5", + "name": "Aquila Riddle", + "registered_at": "Thu, 27 Aug 2015 08:17:24 -0700", + "address": "Ap #187-9582 Primis St.", + "city": "Tacoma", + "state": "WA", + "postal_code": "73251", + "phone": "(925) 161-2223", + "account_credit": 17.82 + }, + { + "id": "6", + "name": "Phyllis Russell", + "registered_at": "Wed, 02 Apr 2014 21:44:46 -0700", + "address": "746-8511 Ipsum Ave", + "city": "Boise", + "state": "Idaho", + "postal_code": "76759", + "phone": "(961) 964-5158", + "account_credit": 88.67 + } + ], + "previous_customers": [ + { + "id": "9", + "name": "Jacqueline Perry", + "registered_at": "Thu, 23 Jul 2015 10:18:35 -0700", + "address": "Ap #288-7228 Dis Rd.", + "city": "Anchorage", + "state": "AK", + "postal_code": "99789", + "phone": "(479) 207-8414", + "account_credit": 96.28 + }, + { + "id": "5", + "name": "Aquila Riddle", + "registered_at": "Thu, 27 Aug 2015 08:17:24 -0700", + "address": "Ap #187-9582 Primis St.", + "city": "Tacoma", + "state": "WA", + "postal_code": "73251", + "phone": "(925) 161-2223", + "account_credit": 17.82 + }, + … + ] + } -## RENTALS + +## Rentals __Endpoint__ -`POST /customers/{:id}/rental/{:title}` - maybe change it be searching for movie id instead of movie title? +`POST /customers/{:id}/rental/{:title}` +maybe change it be searching for movie id instead of movie title? - creates new rental entry - customer_id, movie_id, checkout_date, due_date of +7 days later, return_date == nil - on success... +Creates a new rental entry. - PUT updates inventory_avail -1 for that movie - updates customer account_credit -$X rental fee +PUT updates inventory_avail -1 for that movie + updates customer account_credit -$X rental fee -RENTALS-- Checkin ******* +__Request Parameters__ -PUT '/customers/:id/rental/:title' - updates return_date to Time.now (rental record) - updates inventory_avail +1 for that movie +| Path Parameter | Value | +| :---------------| :------------------------| +| `id` | The ID of the movie. | +| `title` | The title of the movie. | -GET '/rentals/overdue' - array of customers with all their overdue movies - overdue = current_date > due_date && return_date == nil +__Response__ - { customers: [ - { name1 : "something", - overdue_movies: [ - { title1 : "", - release_date : dateTime, - }, - { title2 : "", - release_date : dateTime, - } - ] - }, + { + "1": { + "customer_id": "5", + "name": "Aquila Riddle", + "movie_id": "", + "title": "Close Encounters of the Third Kind", + "checkout_date": "Thu, Sept 17 2015 16:26:30 -0700", + "due_date": "Fri, Sept 25 2015 00:00:00 -0700", + "return_date": null + } + } - { name2 : "something", - overdue_movies: [ - { title1 : "", - release_date : dateTime, - }, - { title2 : "", - release_date : dateTime, - } - ] - }, +*** + +__Endpoint__ +`PUT /customers/{:id}/rental/{:title}` +updates return_date to Time.now (rental record) +updates inventory_avail +1 for that movie + +__Request Parameters__ + +| Path Parameter | Value | +| :---------------| :------------------------| +| `id` | The ID of the movie. | +| `title` | The title of the movie. | + +__Response__ + + { + "rental": { + "customer_id": "5", + "name": "Aquila Riddle", + "movie_id": "", + "title": "Close Encounters of the Third Kind", + "checkout_date": "Thu, Sept 17 2015 16:26:30 -0700", + "due_date": "Fri, Sept 25 2015 00:00:00 -0700", + "return_date": "Wed, Sept 23 2015 04:20:45 -0700" + } + } + +*** + +__Endpoint__ +`GET /rentals/overdue` +array of customers with all their overdue movies +overdue = current_date > due_date && return_date == nil + +__Response__ + + { + "customers": [ + { + "id": "6", + "name" : "Phyllis Russell", + "overdue_movies": [ + { + "id": + "title" : "", + }, + { + "id": + "title" : "", + } + ] + }, + + { + "id": "4", + "name" : "Carolyn Chandler", + "overdue_movies": [ + { + "id": + "title" : "", + } + ] + }, + … ] } From 523cf9ae797fa51b26ee15b26103e6e9908bb7b9 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Fri, 18 Sep 2015 09:47:52 -0700 Subject: [PATCH 18/72] =?UTF-8?q?Added=20a=20semicolon=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/customers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/customers.js b/controllers/customers.js index 0166180..a40c710 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -10,7 +10,7 @@ exports.customersController = { // loop var results = { customers: [] - } + }; return res.status(200).json(results); }, From 7e747cf06412b13390d27be5456131ad528ac6e6 Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 18 Sep 2015 11:45:40 -0700 Subject: [PATCH 19/72] Moved db.close() so that it waits for the query to happen before closing the db connection. --- database.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/database.js b/database.js index b636190..6f0cf63 100644 --- a/database.js +++ b/database.js @@ -15,10 +15,12 @@ StoreDatabase.prototype = { db.all(statement, function(err, res) { // we only get a callback if it's successful if (callback) { callback(res); } + + db.close(); }); + }); - db.close(); } }; From f28c04b0c62c7977668a16b2aac8c75a95234dd1 Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 18 Sep 2015 12:08:20 -0700 Subject: [PATCH 20/72] Renamed res to result for consistency and clarity --- database.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database.js b/database.js index 6f0cf63..8679cba 100644 --- a/database.js +++ b/database.js @@ -12,9 +12,9 @@ StoreDatabase.prototype = { db.serialize(function() { // statement == some SQL string - db.all(statement, function(err, res) { + db.all(statement, function(err, result) { // we only get a callback if it's successful - if (callback) { callback(res); } + if (callback) { callback(result); } db.close(); }); From 716ae6e48a7229f75a83bb6eb8d157d5559bc296 Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 18 Sep 2015 12:09:26 -0700 Subject: [PATCH 21/72] Refactoring how we are structuring our routes and controllers with callbacks. --- controllers/customers.js | 70 +++++++++++++++++---------------------- db/test.db | Bin 0 -> 2048 bytes routes/customers.js | 14 +++++--- 3 files changed, 39 insertions(+), 45 deletions(-) create mode 100644 db/test.db diff --git a/controllers/customers.js b/controllers/customers.js index 0166180..7897d01 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -1,53 +1,43 @@ "use strict"; -var Database = require('../database'); +var Database = require('../database'); // Node module; Pulling in db object we made in a dif file -exports.customersController = { +var customersController = { - customers: function(req, res) { - var customers = Database.query("SELECT * FROM customers"); + all_customers: function(req, callback) { + var statement = "SELECT * FROM customers"; - // loop - var results = { - customers: [] - } + // pull things out of the req (like order_by, etc.) + + var customers = Database.query(statement, function(res) { + // prepare json object + + // loop + var results = { + customers: [] + } + + callback(customers); + }); - return res.status(200).json(results); }, - customer: function(req, res) { - var results = { - id: , - name: , - registered_at: , - address: , - city: , - state: , - postal_code:, - phone: , - account_credit: - }; - - return res.status(200).json(results); - } - - // database_test: function(req, res) { - // var db = new Database(); - // db.test(); - // - // return res.status(200).send("plain text message"); - // }, - - // zomg: function zomg(req, res) { + // customer: function(req, res) { // var results = { - // zomg: "zomg it worked!", - // moar: "zomg moar" + // id: , + // name: , + // registered_at: , + // address: , + // city: , + // state: , + // postal_code:, + // phone: , + // account_credit: // }; - // + // return res.status(200).json(results); - // }, - // - // another_endpoint: function another_endpoint(req, res) { - // return res.status(200).json({ why: "I don't know." }); // } }; + +module.exports = customersController + diff --git a/db/test.db b/db/test.db new file mode 100644 index 0000000000000000000000000000000000000000..21b1895594fafa32cf6f7e1b16d659eb17f49192 GIT binary patch literal 2048 zcmWFz^vNtqRY=P(%1ta$FlJz3U}R))P*7lCU|`;40x zsEUz!9|I7Lg3%Bd4FRf!fCD3&xV$`LU`b+9PHJ*#aY=q|YEdzq!Q>p|>KNjx5aQ_M n0;3@?*h2sS6|5cj literal 0 HcmV?d00001 diff --git a/routes/customers.js b/routes/customers.js index e84c52c..616b5bf 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -1,17 +1,21 @@ var express = require('express'); var router = express.Router(); -var customer_exports = require('../controllers/customers'); +var customersController = require('../controllers/customers'); /* GET customers listing. */ // "/customers " router.get('/', function(req, res, next) { - return customer_exports.customersController.customers(req, res); + // res = express' response object (how it responds to the GET request) + var return_data = customersController.all_customers(req, function(err, result) { + res.send(200).json(result); + }) + }); // "/customers/{:id}" -router.get('/:id', function(req, res, next) { - return customer_exports.customersController.customer(req, res); -}); +// router.get('/:id', function(req, res, next) { +// return customersController.customer(req, res); +// }); module.exports = router; From df7deaa393cef624f9ac9ce4d1f1345fbbc97986 Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 18 Sep 2015 14:52:30 -0700 Subject: [PATCH 22/72] Got the GET all customers route and query functionality working in the customersController. --- controllers/customers.js | 13 ++++++------ database.js | 2 +- routes/customers.js | 10 +++++++-- test/customer_controller_tests.js | 34 +++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 test/customer_controller_tests.js diff --git a/controllers/customers.js b/controllers/customers.js index efabbca..d6b3c31 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -6,17 +6,16 @@ var customersController = { all_customers: function(req, callback) { var statement = "SELECT * FROM customers"; + var db = new Database('db/development.db'); // pull things out of the req (like order_by, etc.) - var customers = Database.query(statement, function(res) { - // prepare json object + db.query(statement, function(err, result) { - // loop - var results = { - customers: [] - } + var json_results = { + customers: result + }; - callback(customers); + callback(err, json_results); }); }, diff --git a/database.js b/database.js index 8679cba..7b3a587 100644 --- a/database.js +++ b/database.js @@ -14,7 +14,7 @@ StoreDatabase.prototype = { // statement == some SQL string db.all(statement, function(err, result) { // we only get a callback if it's successful - if (callback) { callback(result); } + if (callback) { callback(err, result); } db.close(); }); diff --git a/routes/customers.js b/routes/customers.js index 616b5bf..09c3d30 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -8,8 +8,14 @@ var customersController = require('../controllers/customers'); router.get('/', function(req, res, next) { // res = express' response object (how it responds to the GET request) var return_data = customersController.all_customers(req, function(err, result) { - res.send(200).json(result); - }) + + if (err) { + res.status(500).json(err); + } else { + res.status(200).json(result); + }; + + }); }); diff --git a/test/customer_controller_tests.js b/test/customer_controller_tests.js new file mode 100644 index 0000000..d12d98f --- /dev/null +++ b/test/customer_controller_tests.js @@ -0,0 +1,34 @@ +var assert = require("assert"); +var customersController = require("../controllers/customers"); + +describe("customersController", function() { + + beforeEach(function(done) { + db_cleaner = new sqlite3.Database('db/test.db'); + db_cleaner.serialize(function() { + db_cleaner.exec( + "BEGIN; \ + DELETE FROM customers; \ + INSERT INTO customers(name, registered_at, address, city, state, postal_code, phone, account_credit) \ + VALUES('Sarah', 'Wed', 'Ipsum Rd', 'Seattle', 'WA', '12345', '(123) 123-4567', 25.15), \ + ('Jane', 'Thurs', '123 St', 'San Jose', 'CA', '56789', '(345) 124-2984', 12.00); \ + COMMIT;" + , function(err) { + db_cleaner.close(); + done(); + } + ); + }); + }); + + it("has an 'all_customers' property that is a function", function() { + assert.equal(typeof customersController.all_customers, "function"); + }); + + it("returns a json object", function(done) { + customersController.all_customers(req, function(err, result) { + assert(typeof result, "json"); + }); + }); + +}) \ No newline at end of file From fc4629294c21f58cdadec7588d5ce505d83f313c Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 18 Sep 2015 15:07:40 -0700 Subject: [PATCH 23/72] Can now query for a single customer's info --- controllers/customers.js | 32 +++++++++++++++----------------- routes/customers.js | 18 ++++++++++++++---- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index d6b3c31..4336d8c 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -4,10 +4,11 @@ var Database = require('../database'); // Node module; Pulling in db object we m var customersController = { + // maybe move the var db = ... out here? + all_customers: function(req, callback) { var statement = "SELECT * FROM customers"; var db = new Database('db/development.db'); - // pull things out of the req (like order_by, etc.) db.query(statement, function(err, result) { @@ -20,21 +21,18 @@ var customersController = { }, - // customer: function(req, res) { - // var results = { - // id: , - // name: , - // registered_at: , - // address: , - // city: , - // state: , - // postal_code:, - // phone: , - // account_credit: - // }; - - // return res.status(200).json(results); - // } + customer: function(req, callback) { + var statement = "SELECT * FROM customers WHERE id = " + req.params.id + ";"; + var db = new Database('db/development.db'); + + db.query(statement, function(err, result) { + + var json_result = { + customer: result[0] + }; + callback(err, json_result); + }); + } }; -module.exports = customersController +module.exports = customersController; diff --git a/routes/customers.js b/routes/customers.js index 09c3d30..340cd14 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -7,7 +7,8 @@ var customersController = require('../controllers/customers'); // "/customers " router.get('/', function(req, res, next) { // res = express' response object (how it responds to the GET request) - var return_data = customersController.all_customers(req, function(err, result) { + + customersController.all_customers(req, function(err, result) { if (err) { res.status(500).json(err); @@ -20,8 +21,17 @@ router.get('/', function(req, res, next) { }); // "/customers/{:id}" -// router.get('/:id', function(req, res, next) { -// return customersController.customer(req, res); -// }); +router.get('/:id', function(req, res, next) { + customersController.customer(req, function(err, result) { + + if (err) { + res.status(500).json(err); + } else { + res.status(200).json(result); + }; + + }) + +}); module.exports = router; From e391ee74658aeb55a962e41e3107affa48f0289a Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 18 Sep 2015 15:16:04 -0700 Subject: [PATCH 24/72] Created movies.js controller file with stubbed out functions. --- controllers/movies.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 controllers/movies.js diff --git a/controllers/movies.js b/controllers/movies.js new file mode 100644 index 0000000..a3d1d58 --- /dev/null +++ b/controllers/movies.js @@ -0,0 +1,15 @@ +"use strict"; + +var Database = require('../database'); // Node module; Pulling in db object we made in a dif file + +var moviesController = { + // maybe move the var db = ... out here? + all_movies: function() { + + }, + movie: function() { + // Amira + } +}; + +module.exports = moviesController; \ No newline at end of file From 5947c13430e6780e2dc2b4b6430f344fc2503839 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Fri, 18 Sep 2015 15:28:42 -0700 Subject: [PATCH 25/72] Created endpoints for './movies' and './movies/{:id}'. --- app.js | 3 +++ controllers/movies.js | 27 +++++++++++++++++++++++---- routes/movies.js | 27 +++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 routes/movies.js diff --git a/app.js b/app.js index 5b087ce..33cc816 100644 --- a/app.js +++ b/app.js @@ -26,6 +26,9 @@ app.use(express.static(path.join(__dirname, 'public'))); var customers = require('./routes/customers'); app.use('/customers', customers); +var movies = require('./routes/movies'); +app.use('/movies', movies); + // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); diff --git a/controllers/movies.js b/controllers/movies.js index a3d1d58..4c0efd1 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -4,12 +4,31 @@ var Database = require('../database'); // Node module; Pulling in db object we m var moviesController = { // maybe move the var db = ... out here? - all_movies: function() { + all_movies: function(req, callback) { + var statement = "SELECT * FROM movies;"; + var db = new Database('db/development.db'); + db.query(statement, function(err, result) { + var json_result = { + movies: result + }; + + callback(err, json_result); + }); }, - movie: function() { - // Amira + + movie: function(req, callback) { + var statement = "SELECT * FROM movies WHERE id = " + req.params.id + ";"; + var db = new Database('db/development.db'); + + db.query(statement, function(err, result) { + var json_result = { + movie: result[0] + }; + + callback(err, json_result); + }); } }; -module.exports = moviesController; \ No newline at end of file +module.exports = moviesController; diff --git a/routes/movies.js b/routes/movies.js new file mode 100644 index 0000000..5eeb2a9 --- /dev/null +++ b/routes/movies.js @@ -0,0 +1,27 @@ +var express = require('express'); +var router = express.Router(); +var moviesController = require('../controllers/movies'); + +// "GET ./movies/" +router.get("/", function(req, res, next) { + moviesController.all_movies(req, function(err, result) { + if (err) { + res.status(500).json(err); + } else { + res.status(200).json(result); + } + }) +}) + +// "GET ./movies/{:id}" +router.get("/:id", function(req, res, next) { + moviesController.movie(req, function(err, result) { + if (err) { + res.status(500).json(err); + } else { + res.status(200).json(result); + } + }) +}) + +module.exports = router; From c48abf4e7772981d63fa1c85feee0ce586724ef1 Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 18 Sep 2015 15:35:53 -0700 Subject: [PATCH 26/72] Added '/zomg' GET response per project baseline requirements. --- app.js | 5 ++--- routes/index.js | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/app.js b/app.js index 33cc816..05ad5ee 100644 --- a/app.js +++ b/app.js @@ -19,9 +19,8 @@ app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); -// NOTE: Do we even need this…? -// var routes = require('./routes/index'); -// app.use('/', routes); +var routes = require('./routes/index'); +app.use('/', routes); var customers = require('./routes/customers'); app.use('/customers', customers); diff --git a/routes/index.js b/routes/index.js index ecca96a..169a3bd 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,9 +1,9 @@ var express = require('express'); var router = express.Router(); -/* GET home page. */ -router.get('/', function(req, res, next) { - res.render('index', { title: 'Express' }); +// Project Baseline Requirement +router.get('/zomg', function(req, res, next) { + res.json('it works!'); }); module.exports = router; From 573389644d4d3be94e737725ea5c63ceb035ddbc Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 18 Sep 2015 16:31:24 -0700 Subject: [PATCH 27/72] WIP querying multiple times to movies db for customer renting and rented info. --- controllers/customers.js | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index 4336d8c..9f21329 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -23,15 +23,39 @@ var customersController = { customer: function(req, callback) { var statement = "SELECT * FROM customers WHERE id = " + req.params.id + ";"; - var db = new Database('db/development.db'); + var customer_renting_statment = + "SELECT * FROM rentals \ + WHERE customer_id = " + req.params.id + "AND \ + return_date IS NULL;"; - db.query(statement, function(err, result) { + var customer_rented_statment = + "SELECT * FROM rentals \ + WHERE customer_id = " + req.params.id + "AND \ + return_date IS NOT NULL;"; - var json_result = { - customer: result[0] - }; - callback(err, json_result); + var db = new Database('db/development.db'); + + var customer_info = db.query(statement, function(err, result) { + return result[0]; }); + + var customer_renting = db.query(customer_renting_statment, function(err, result) { + return result; + }) + + var customer_rented = db.query(customer_rented_statment, function(err, result) { + return result; + }) + + console.log(customer_info); + + var json_result = { + customer: customer_info, + renting: customer_renting, + rented: customer_rented + }; + + callback(err, json_result); } }; From 994b7ae7049ddce63695bf6ab925b588f4eb1326 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Sat, 19 Sep 2015 10:31:55 -0700 Subject: [PATCH 28/72] Sorts results by order_by query. --- controllers/movies.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/controllers/movies.js b/controllers/movies.js index 4c0efd1..6a23bbc 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -5,7 +5,8 @@ var Database = require('../database'); // Node module; Pulling in db object we m var moviesController = { // maybe move the var db = ... out here? all_movies: function(req, callback) { - var statement = "SELECT * FROM movies;"; + var column = req.query.order_by ? req.query.order_by : "id"; + var statement = "SELECT * FROM movies ORDER BY " + column + " ASC;"; var db = new Database('db/development.db'); db.query(statement, function(err, result) { From 5ec641ff0eb59ebc08223042390b4feb2a61a501 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Sat, 19 Sep 2015 10:52:18 -0700 Subject: [PATCH 29/72] Can now find a movie by its title. --- app.js | 1 + controllers/movies.js | 3 ++- routes/movies.js | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app.js b/app.js index 05ad5ee..03d0522 100644 --- a/app.js +++ b/app.js @@ -27,6 +27,7 @@ app.use('/customers', customers); var movies = require('./routes/movies'); app.use('/movies', movies); +app.use('/movie', movies); // catch 404 and forward to error handler app.use(function(req, res, next) { diff --git a/controllers/movies.js b/controllers/movies.js index 6a23bbc..b3a384f 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -19,7 +19,8 @@ var moviesController = { }, movie: function(req, callback) { - var statement = "SELECT * FROM movies WHERE id = " + req.params.id + ";"; + var title = req.params.title + var statement = "SELECT * FROM movies WHERE title LIKE '" + title + "';"; var db = new Database('db/development.db'); db.query(statement, function(err, result) { diff --git a/routes/movies.js b/routes/movies.js index 5eeb2a9..5138245 100644 --- a/routes/movies.js +++ b/routes/movies.js @@ -13,8 +13,8 @@ router.get("/", function(req, res, next) { }) }) -// "GET ./movies/{:id}" -router.get("/:id", function(req, res, next) { +// "GET ./movies/{:title}" +router.get("/:title", function(req, res, next) { moviesController.movie(req, function(err, result) { if (err) { res.status(500).json(err); From 6c70ef87fe0205dbb8655e1d5a6639eedc9d1cb5 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Sat, 19 Sep 2015 10:58:39 -0700 Subject: [PATCH 30/72] Elaborated on endpoints. --- endpoints.md | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/endpoints.md b/endpoints.md index 0d61ceb..53e3d2a 100644 --- a/endpoints.md +++ b/endpoints.md @@ -118,27 +118,43 @@ __Response__ { "movies": [ - + { + "id": 1, + "title": "Psycho", + "overview": "When larcenous real estate clerk Marion Crane goes on the lam with a wad of cash and hopes of starting a new life, she ends up at the notorious Bates Motel, where manager Norman Bates cares for his housebound mother. The place seems quirky, but fine… until Marion decides to take a shower.", + "release_date": "1960-06-16", + "inventory_total": 8, + "inventory_avail": 8 + }, + { + "id": 2, + "title": "Jaws", + "overview": "An insatiable great white shark terrorizes the townspeople of Amity Island, The police chief, an oceanographer and a grizzled shark hunter seek to destroy the bloodthirsty beast.", + "release_date": "1975-06-19", + "inventory_total": 6, + "inventory_avail": 6 + }, + … ] } *** __Endpoint__ -`GET ./movies/{:title}` +`GET ./movie/{:title}` Returns movies that match the title query. +E.g. ".movie/jaws", "./movie/north%20by%20northwest" __Request Parameters__ -| Path Parameter | Value | -| :------------------| :------------- | +| Path Parameter | Value | +| :------------------| :------------------------| | `title` | The title of the movie. | __Response__ { - "movies" : [ - { + "movies" : { "title": "The Night of the Hunter", "overview": "Harry Powell marries and murders widows for their money, believing he is helping God do away with women who arouse men's carnal instincts. Arrested for auto theft, he shares a cell with condemned killer Ben Harper and tries to get him to reveal the whereabouts of the $10,000 he stole. Only Ben's nine-year-old son, John, and four-year-old daughter, Pearl, know the money is in Pearl's doll; and they have sworn to their father to keep this secret. After Ben is executed, Preacher goes to Cresap's Landing to court Ben's widow, Willa. When he overwhelms her with his Scripture quoting, sermons, and hymns, she agrees to marry him. On their wedding night, he tells her they will never have sex because it is sinful.", "release_date": "1955-07-26", @@ -150,7 +166,7 @@ __Response__ *** __Endpoint__ -`GET /movies/{:title}/customers` +`GET /movie/{:title}/customers` default is sorting by id __Request Parameters__ From 7dbf95c36951d09b06c7ca7432d5758be1e9225e Mon Sep 17 00:00:00 2001 From: amirahaile Date: Mon, 21 Sep 2015 09:46:07 -0700 Subject: [PATCH 31/72] Created rental seed data. --- utils/rentals.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ utils/schema.js | 2 ++ utils/seeds.js | 28 ++++++++++++++++++------ 3 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 utils/rentals.js diff --git a/utils/rentals.js b/utils/rentals.js new file mode 100644 index 0000000..4834674 --- /dev/null +++ b/utils/rentals.js @@ -0,0 +1,56 @@ +"use strict"; + +var customers = require('./customers'); +var movies = require('./movies'); +var rentals = []; + +for(var i = 0; i < customers.length; i++) { + var customer = customers[i]; + // assuming our db creates these in over + // looking for the ID (which doesn't include 0) + var movie1_id = Math.floor(Math.random() * movies.length) + 1; + var movie2_id = Math.floor(Math.random() * movies.length) + 1; + var movie3_id = Math.floor(Math.random() * movies.length) + 1; + // using it for the INDEX (which starts at 0) + var movie1 = movies[movie1_id - 1]; + var movie2 = movies[movie2_id - 1]; + var movie3 = movies[movie3_id - 1]; + + var current_rental = { + "customer_id": customer.id, + "name": customer.name, + "movie_id": movie1_id, + "title": movie1.title, + "checkout_date": "2015-09-19", + "due_date": "3016-09-19", + "return_date": null + } + + rentals.push(current_rental); + + var past_rental = { + "customer_id": customer.id, + "name": customer.name, + "movie_id": movie2_id, + "title": movie2.title, + "checkout_date": "2014-09-09", + "due_date": "2014-09-16", + "return_date": "2014-09-10" + } + + rentals.push(past_rental); + + var overdue_rental = { + "customer_id": customer.id, + "name": customer.name, + "movie_id": movie3_id, + "title": movie3.title, + "checkout_date": "2014-09-19", + "due_date": "2014-09-26", + "return_date": null + } + + rentals.push(overdue_rental); +} + +module.exports = rentals; diff --git a/utils/schema.js b/utils/schema.js index 9c7324e..67334eb 100644 --- a/utils/schema.js +++ b/utils/schema.js @@ -25,7 +25,9 @@ var customer_fields = [ var rental_fields = [ ['customer_id', 'integer'], + ['name', 'text'], ['movie_id', 'integer'], + ['title', 'text'], ['checkout_date', 'text'], ['due_date', 'text'], ['return_date', 'text'] diff --git a/utils/seeds.js b/utils/seeds.js index ed4745b..5f532c9 100644 --- a/utils/seeds.js +++ b/utils/seeds.js @@ -16,11 +16,11 @@ var customer_statement = db.prepare( VALUES (?, ?, ?, ?, ?, ?, ?, ?);" ); -// var movies = require('./movies'); -// var movie_statement = db.prepare( -// "INSERT INTO movies(title, overview, release_date, inventory_total, inventory_avail) \ -// VALUES (?, ?, ?, ?, ?);" -// ); +var rentals = require('./rentals'); +var rental_statement = db.prepare( + "INSERT INTO rentals(customer_id, name, movie_id, title, checkout_date, due_date, return_date) \ + VALUES (?, ?, ?, ?, ?, ?, ?);" +); db.serialize(function() { // loop through movies @@ -58,7 +58,23 @@ db.serialize(function() { customer_statement.finalize(); + // loop through rentals + for(var i = 0; i < rentals.length; i++) { + var rental = rentals[i]; + + // insert each into the db + rental_statement.run( + rental.customer_id, + rental.name, + rental.movie_id, + rental.title, + rental.checkout_date, + rental.due_date, + rental.return_date + ); + } + + rental_statement.finalize(); }); db.close(); - From 8473ad649c52f3f1f930c938ef878dd5f383a903 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Mon, 21 Sep 2015 09:49:49 -0700 Subject: [PATCH 32/72] Fixed movie title query. Returns fuzzy matches. --- controllers/movies.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/controllers/movies.js b/controllers/movies.js index b3a384f..b4be557 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -20,12 +20,12 @@ var moviesController = { movie: function(req, callback) { var title = req.params.title - var statement = "SELECT * FROM movies WHERE title LIKE '" + title + "';"; + var statement = "SELECT * FROM movies WHERE title LIKE '%" + title + "%';"; var db = new Database('db/development.db'); db.query(statement, function(err, result) { var json_result = { - movie: result[0] + movie: result }; callback(err, json_result); From 1d70b5cbe18af20f9ac7e4efff048ecd43f0c23f Mon Sep 17 00:00:00 2001 From: Kari Date: Mon, 21 Sep 2015 10:00:03 -0700 Subject: [PATCH 33/72] Added line to customers controller to order by id unless the query specifies another order_by param --- controllers/customers.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/controllers/customers.js b/controllers/customers.js index 9f21329..52c72d2 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -6,8 +6,10 @@ var customersController = { // maybe move the var db = ... out here? + // "/customers?order_by=name" all_customers: function(req, callback) { - var statement = "SELECT * FROM customers"; + var column = req.query.order_by ? req.query.order_by : "id"; + var statement = "SELECT * FROM customers ORDER BY " + column + " ASC;"; var db = new Database('db/development.db'); db.query(statement, function(err, result) { From 009aa0d47fd49db5d66eb3bc2d182d550b349467 Mon Sep 17 00:00:00 2001 From: Kari Date: Mon, 21 Sep 2015 11:00:50 -0700 Subject: [PATCH 34/72] Callback Hell insanity and then we discovered join queries... --- controllers/customers.js | 71 ++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index 52c72d2..3d2e0f7 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -24,38 +24,67 @@ var customersController = { }, customer: function(req, callback) { + var json_result = {}; + var statement = "SELECT * FROM customers WHERE id = " + req.params.id + ";"; - var customer_renting_statment = - "SELECT * FROM rentals \ - WHERE customer_id = " + req.params.id + "AND \ - return_date IS NULL;"; + var customer_renting_statement = + "SELECT * FROM rentals WHERE customer_id = " + req.params.id + " AND return_date IS NULL;"; - var customer_rented_statment = + var customer_rented_statement = "SELECT * FROM rentals \ - WHERE customer_id = " + req.params.id + "AND \ + WHERE customer_id = " + req.params.id + " AND \ return_date IS NOT NULL;"; var db = new Database('db/development.db'); - var customer_info = db.query(statement, function(err, result) { - return result[0]; - }); + function firstQuery(err, this_query, callback) { + db.query(this_query, function(err, result) { + json_result.customer = result[0]; + }); - var customer_renting = db.query(customer_renting_statment, function(err, result) { - return result; - }) + callback(err, customer_renting_statement, thirdQuery); + }; - var customer_rented = db.query(customer_rented_statment, function(err, result) { - return result; - }) + function secondQuery(err, this_query, callback) { + db.query(this_query, function(err, result) { + json_result.renting = result; + }); - console.log(customer_info); + callback(err, customer_rented_statement); + }; - var json_result = { - customer: customer_info, - renting: customer_renting, - rented: customer_rented - }; + function thirdQuery(err, this_query) { + db.query(customer_rented_statement, function(err, result) { + json_result.rented = result; + console.log(json_result); + }); + }; + + + firstQuery(err, statement, secondQuery); + + + // var customer_info = db.query(statement, function(err, result) { + // json_result.customer = result[0]; + // }); + + // var customer_renting = db.query(customer_renting_statement, function(err, result) { + // json_result.renting = result; + // }) + + // var customer_rented = db.query(customer_rented_statement, function(err, result) { + // json_result.rented = result; + // }) + + // console.log("customer_info = " + customer_info); + // console.log("customer_renting = " + customer_renting); + // console.log("customer_rented = " + customer_rented); + + // var json_result = { + // customer: customer_info, + // renting: customer_renting, + // rented: customer_rented + // }; callback(err, json_result); } From c0d18aef2b24748c4734df01a3d32a1a9b3624e2 Mon Sep 17 00:00:00 2001 From: Kari Date: Mon, 21 Sep 2015 11:44:09 -0700 Subject: [PATCH 35/72] Updated customer search query to pull in information about their rentals. Formatted it to appear as we want it to in our json response. --- controllers/customers.js | 94 ++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 56 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index 3d2e0f7..d79ae10 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -24,70 +24,52 @@ var customersController = { }, customer: function(req, callback) { - var json_result = {}; - - var statement = "SELECT * FROM customers WHERE id = " + req.params.id + ";"; - var customer_renting_statement = - "SELECT * FROM rentals WHERE customer_id = " + req.params.id + " AND return_date IS NULL;"; - - var customer_rented_statement = - "SELECT * FROM rentals \ - WHERE customer_id = " + req.params.id + " AND \ - return_date IS NOT NULL;"; - + var statement = "SELECT * FROM customers, rentals WHERE customers.id = " + req.params.id + " AND rentals.customer_id = " + req.params.id + ";"; var db = new Database('db/development.db'); - function firstQuery(err, this_query, callback) { - db.query(this_query, function(err, result) { - json_result.customer = result[0]; - }); - - callback(err, customer_renting_statement, thirdQuery); - }; - - function secondQuery(err, this_query, callback) { - db.query(this_query, function(err, result) { - json_result.renting = result; - }); - - callback(err, customer_rented_statement); + db.query(statement, function(err, result) { + + var customer_info = { + id: result[0].customer_id, + name: result[0].name, + registered_at: result[0].registered_at, + address: result[0].address, + city: result[0].city, + state: result[0].state, + postal_code: result[0].postal_code, + phone: result[0].phone, + account_credit: result[0].account_credit }; - function thirdQuery(err, this_query) { - db.query(customer_rented_statement, function(err, result) { - json_result.rented = result; - console.log(json_result); - }); - }; - + var renting_movies = []; + var rented_movies = []; - firstQuery(err, statement, secondQuery); - - - // var customer_info = db.query(statement, function(err, result) { - // json_result.customer = result[0]; - // }); - - // var customer_renting = db.query(customer_renting_statement, function(err, result) { - // json_result.renting = result; - // }) - - // var customer_rented = db.query(customer_rented_statement, function(err, result) { - // json_result.rented = result; - // }) - - // console.log("customer_info = " + customer_info); - // console.log("customer_renting = " + customer_renting); - // console.log("customer_rented = " + customer_rented); + for(var i = 0; i < result.length; i++) { + var movie = { + id: result[i].movie_id, + title: result[i].title, + checkout_date: result[i].checkout_date, + due_date: result[i].due_date, + return_date: result[i].return_date + }; - // var json_result = { - // customer: customer_info, - // renting: customer_renting, - // rented: customer_rented - // }; + if(movie.return_date == null) { + renting_movies.push(movie); + } else { + rented_movies.push(movie); + } + } + + var json_results = { + account: customer_info, + renting: renting_movies, + rented: rented_movies + }; - callback(err, json_result); + callback(err, json_results); + }); } + }; module.exports = customersController; From de8597fd7a89aa1b3a5c119a498d0a985bec4889 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Mon, 21 Sep 2015 13:29:59 -0700 Subject: [PATCH 36/72] Added number & page query params for customer. --- endpoints.md | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/endpoints.md b/endpoints.md index 53e3d2a..0718c2a 100644 --- a/endpoints.md +++ b/endpoints.md @@ -4,18 +4,18 @@ The following are all the endpoints available from our Video Store API. ## Customer __Endpoint__ -`GET ./customers` -Returns all the information on record of all of our customers. +`GET ./customers` + +Returns all the information on record of our customers. Can be sorted by `name`, `registered_at`, or `postal_code`. Also can be paginated with `number` and `page` (e.g. display the 2nd page of 20 customer records: `./customers?number=20&page=2`). -returns n number of customers (hardcoded?) sorted by name -offset by p records (hardcoded) - all of the attr of customers __Request Parameters__ -| Query Parameter | Value | -| :-------------------| :------------- | -| `order_by ` | _Optional._ Provide this parameter if you would like the customers sorted. Options include: `name`, `registered_at`, or `postal_code`. | +| Query Parameter | Value | +| :-------------- | :------------- | +| `order_by ` | _Optional._ Provide this parameter if you would like the customers sorted. Options include: `name`, `registered_at`, or `postal_code`. When using `name`, customers are sorted by their first name. | +| `number` | An integer that represents the number of customer records you'd like returned. | +| `page` | _Requires `number` query._ The page of customer records you'd like returned. | __Response Format__ @@ -69,7 +69,12 @@ __Request Parameter__ __Response__ { - "customer": { + "account": { + "id": 2, + "name": "Curran Stout", + "registered_at": "Wed, 16 Apr 2014 21:40: -0770" + "address": , + "renting": [ { "id": 1 @@ -141,7 +146,7 @@ __Response__ *** __Endpoint__ -`GET ./movie/{:title}` +`GET ./movies/{:title}` Returns movies that match the title query. E.g. ".movie/jaws", "./movie/north%20by%20northwest" From 4634877b8060023d330736f2fd0c258a7b05bda2 Mon Sep 17 00:00:00 2001 From: Kari Date: Mon, 21 Sep 2015 13:31:13 -0700 Subject: [PATCH 37/72] Add pagination ability for customers search. --- controllers/customers.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index d79ae10..f2775c3 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -6,10 +6,19 @@ var customersController = { // maybe move the var db = ... out here? - // "/customers?order_by=name" + // ALL CUSTOMERS SEARCH... "/customers?order_by=name" + // PAGINATION... "/customers?number=25&page=2" => customers 26-50 all_customers: function(req, callback) { var column = req.query.order_by ? req.query.order_by : "id"; - var statement = "SELECT * FROM customers ORDER BY " + column + " ASC;"; + + if (req.query.number && req.query.page) { + var limit = req.query.number; + var offset = req.query.page * limit - limit; + var statement = "SELECT * FROM customers ORDER BY " + column + " ASC LIMIT " + limit + " OFFSET " + offset + ";"; + } else { + var statement = "SELECT * FROM customers ORDER BY " + column + " ASC;"; + } + var db = new Database('db/development.db'); db.query(statement, function(err, result) { @@ -24,7 +33,7 @@ var customersController = { }, customer: function(req, callback) { - var statement = "SELECT * FROM customers, rentals WHERE customers.id = " + req.params.id + " AND rentals.customer_id = " + req.params.id + ";"; + var statement = "SELECT * FROM customers, rentals WHERE customers.id = " + req.params.id + " AND rentals.customer_id = " + req.params.id + " ORDER BY rentals.checkout_date ASC;"; var db = new Database('db/development.db'); db.query(statement, function(err, result) { From a10bf3731764f2039cfa9b6c305672c5c3628850 Mon Sep 17 00:00:00 2001 From: Kari Date: Mon, 21 Sep 2015 13:34:00 -0700 Subject: [PATCH 38/72] Added pagination feature to movies search. --- controllers/movies.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/controllers/movies.js b/controllers/movies.js index b4be557..9b56697 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -6,7 +6,15 @@ var moviesController = { // maybe move the var db = ... out here? all_movies: function(req, callback) { var column = req.query.order_by ? req.query.order_by : "id"; - var statement = "SELECT * FROM movies ORDER BY " + column + " ASC;"; + + if (req.query.number && req.query.page) { + var limit = req.query.number; + var offset = req.query.page * limit - limit; + var statement = "SELECT * FROM movies ORDER BY " + column + " ASC LIMIT " + limit + " OFFSET " + offset + ";"; + } else { + var statement = "SELECT * FROM movies ORDER BY " + column + " ASC;"; + } + var db = new Database('db/development.db'); db.query(statement, function(err, result) { From bc987082ef18a8fa5ceec60350e081fc993efa62 Mon Sep 17 00:00:00 2001 From: Kari Date: Mon, 21 Sep 2015 15:40:39 -0700 Subject: [PATCH 39/72] Created new endpoint to see rental history of a movie. Also can see all movie info for a specific movie query. --- controllers/movies.js | 55 ++++++++++++++++++++++++++++++++++++++++--- routes/movies.js | 11 +++++++++ 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/controllers/movies.js b/controllers/movies.js index 9b56697..1763424 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -14,7 +14,7 @@ var moviesController = { } else { var statement = "SELECT * FROM movies ORDER BY " + column + " ASC;"; } - + var db = new Database('db/development.db'); db.query(statement, function(err, result) { @@ -27,15 +27,64 @@ var moviesController = { }, movie: function(req, callback) { - var title = req.params.title - var statement = "SELECT * FROM movies WHERE title LIKE '%" + title + "%';"; + var column = req.query.order_by ? req.query.order_by : "title"; + var title = req.params.title + var statement = "SELECT * FROM movies WHERE title LIKE '%" + title + "%' ORDER BY " + column + " ASC;"; + var db = new Database('db/development.db'); db.query(statement, function(err, result) { + var json_result = { movie: result }; + callback(err, json_result); + }); + }, + + movie_rentals: function(req, callback) { + var column = req.query.order_by ? req.query.order_by : "customer_id"; + var title = req.params.title + var statement = + "SELECT \ + rentals.id, rentals.title, rentals.customer_id, rentals.name, \ + rentals.checkout_date, rentals.due_date, rentals.return_date \ + FROM movies, rentals \ + WHERE rentals.movie_id = movies.id AND movies.title LIKE '%" + title + "%' \ + ORDER BY " + column + " ASC;"; + + var db = new Database('db/development.db'); + + db.query(statement, function(err, result) { + + var current_rentals_array = []; + var previous_rentals_array = []; + + for(var i = 0; i < result.length; i++) { + + var rental = { + rental_id: result[i].id, + movie_title: result[i].title, + customer_id: result[i].customer_id, + customer_name: result[i].name, + checkout_date: result[i].checkout_date, + due_date: result[i].due_date, + return_date: result[i].return_date + }; + + if(rental.return_date == null) { + current_rentals_array.push(rental); + } else { + previous_rentals_array.push(rental); + }; + }; + + var json_result = { + current_rentals: current_rentals_array, + previous_rentals: previous_rentals_array + }; + callback(err, json_result); }); } diff --git a/routes/movies.js b/routes/movies.js index 5138245..12bfac0 100644 --- a/routes/movies.js +++ b/routes/movies.js @@ -24,4 +24,15 @@ router.get("/:title", function(req, res, next) { }) }) +// "GET ./movies/{:title}/rentals" +router.get("/:title/rentals", function(req, res, next) { + moviesController.movie_rentals(req, function(err, result) { + if (err) { + res.status(500).json(err); + } else { + res.status(200).json(result); + } + }) +}) + module.exports = router; From cc97537de5777c5dd6bdbb87a9c3e40799fbe7f3 Mon Sep 17 00:00:00 2001 From: Kari Date: Mon, 21 Sep 2015 15:50:20 -0700 Subject: [PATCH 40/72] Moved search query for rental information into a rentals controller with a separate rentals route. --- app.js | 4 +++- controllers/movies.js | 46 ----------------------------------- controllers/rentals.js | 54 ++++++++++++++++++++++++++++++++++++++++++ routes/rentals.js | 16 +++++++++++++ 4 files changed, 73 insertions(+), 47 deletions(-) create mode 100644 controllers/rentals.js create mode 100644 routes/rentals.js diff --git a/app.js b/app.js index 03d0522..b5163a8 100644 --- a/app.js +++ b/app.js @@ -27,7 +27,9 @@ app.use('/customers', customers); var movies = require('./routes/movies'); app.use('/movies', movies); -app.use('/movie', movies); + +var rentals = require('./routes/rentals'); +app.use('/rentals', rentals); // catch 404 and forward to error handler app.use(function(req, res, next) { diff --git a/controllers/movies.js b/controllers/movies.js index 1763424..d9b72d0 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -42,52 +42,6 @@ var moviesController = { callback(err, json_result); }); }, - - movie_rentals: function(req, callback) { - var column = req.query.order_by ? req.query.order_by : "customer_id"; - var title = req.params.title - var statement = - "SELECT \ - rentals.id, rentals.title, rentals.customer_id, rentals.name, \ - rentals.checkout_date, rentals.due_date, rentals.return_date \ - FROM movies, rentals \ - WHERE rentals.movie_id = movies.id AND movies.title LIKE '%" + title + "%' \ - ORDER BY " + column + " ASC;"; - - var db = new Database('db/development.db'); - - db.query(statement, function(err, result) { - - var current_rentals_array = []; - var previous_rentals_array = []; - - for(var i = 0; i < result.length; i++) { - - var rental = { - rental_id: result[i].id, - movie_title: result[i].title, - customer_id: result[i].customer_id, - customer_name: result[i].name, - checkout_date: result[i].checkout_date, - due_date: result[i].due_date, - return_date: result[i].return_date - }; - - if(rental.return_date == null) { - current_rentals_array.push(rental); - } else { - previous_rentals_array.push(rental); - }; - }; - - var json_result = { - current_rentals: current_rentals_array, - previous_rentals: previous_rentals_array - }; - - callback(err, json_result); - }); - } }; module.exports = moviesController; diff --git a/controllers/rentals.js b/controllers/rentals.js new file mode 100644 index 0000000..7cf9ba7 --- /dev/null +++ b/controllers/rentals.js @@ -0,0 +1,54 @@ +"use strict"; + +var Database = require('../database'); // Node module; Pulling in db object we made in a dif file + +var rentalsController = { + + rentals: function(req, callback) { + var column = req.query.order_by ? req.query.order_by : "customer_id"; + var title = req.params.title + var statement = + "SELECT \ + rentals.id, rentals.title, rentals.customer_id, rentals.name, \ + rentals.checkout_date, rentals.due_date, rentals.return_date \ + FROM movies, rentals \ + WHERE rentals.movie_id = movies.id AND movies.title LIKE '%" + title + "%' \ + ORDER BY " + column + " ASC;"; + + var db = new Database('db/development.db'); + + db.query(statement, function(err, result) { + + var current_rentals_array = []; + var previous_rentals_array = []; + + for(var i = 0; i < result.length; i++) { + + var rental = { + rental_id: result[i].id, + movie_title: result[i].title, + customer_id: result[i].customer_id, + customer_name: result[i].name, + checkout_date: result[i].checkout_date, + due_date: result[i].due_date, + return_date: result[i].return_date + }; + + if(rental.return_date == null) { + current_rentals_array.push(rental); + } else { + previous_rentals_array.push(rental); + }; + }; + + var json_result = { + current_rentals: current_rentals_array, + previous_rentals: previous_rentals_array + }; + + callback(err, json_result); + }); + } +}; + +module.exports = rentalsController; diff --git a/routes/rentals.js b/routes/rentals.js new file mode 100644 index 0000000..0fd1ba2 --- /dev/null +++ b/routes/rentals.js @@ -0,0 +1,16 @@ +var express = require('express'); +var router = express.Router(); +var rentalsController = require('../controllers/rentals'); + +// "GET ./rentals/{:title}" +router.get("/:title", function(req, res, next) { + rentalsController.rentals(req, function(err, result) { + if (err) { + res.status(500).json(err); + } else { + res.status(200).json(result); + } + }) +}) + +module.exports = router; \ No newline at end of file From 4eec6e292a4d71f47afe7f3615aac7329faa00b9 Mon Sep 17 00:00:00 2001 From: Kari Date: Mon, 21 Sep 2015 15:53:11 -0700 Subject: [PATCH 41/72] Added new route for overdue rentals. Namespaced the rentals by title search query so they don't conflict. --- routes/rentals.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/routes/rentals.js b/routes/rentals.js index 0fd1ba2..a5fe349 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -2,8 +2,8 @@ var express = require('express'); var router = express.Router(); var rentalsController = require('../controllers/rentals'); -// "GET ./rentals/{:title}" -router.get("/:title", function(req, res, next) { +// "GET ./rentals/title/{:title}" +router.get("/title/:title", function(req, res, next) { rentalsController.rentals(req, function(err, result) { if (err) { res.status(500).json(err); @@ -13,4 +13,15 @@ router.get("/:title", function(req, res, next) { }) }) +// "GET ./rentals/overdue" +router.get("/overdue", function(req, res, next) { + rentalsController.rentals_overdue(req, function(err, result) { + if (err) { + res.status(500).json(err); + } else { + res.status(200).json(result); + } + }) +}) + module.exports = router; \ No newline at end of file From 9446cb5a7cb0753b4db58e45e86d7a7c938c47d3 Mon Sep 17 00:00:00 2001 From: Kari Date: Tue, 22 Sep 2015 11:02:53 -0700 Subject: [PATCH 42/72] WIP rentals_overdue controller function for the overdue endpoint. --- controllers/rentals.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/controllers/rentals.js b/controllers/rentals.js index 7cf9ba7..e568ae5 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -46,6 +46,30 @@ var rentalsController = { previous_rentals: previous_rentals_array }; + callback(err, json_result); + }); + }, + + rentals_overdue: function(req, callback) { + var column = req.query.order_by ? req.query.order_by : "customer_id"; + var statement = + "SELECT \ + rentals.id, rentals.title, rentals.customer_id, rentals.name, \ + rentals.checkout_date, rentals.due_date, rentals.return_date \ + FROM movies, rentals \ + WHERE rentals.movie_id = movies.id \ + AND movies.title LIKE '%" + title + "%' \ + AND rentals.return_date + ORDER BY " + column + " ASC;"; + + var db = new Database('db/development.db'); + + db.query(statement, function(err, result) { + + var json_result = { + overdue_movies: result + }; + callback(err, json_result); }); } From 9e84ffeda693a0dc8fc46ef921f3cd86d2631f45 Mon Sep 17 00:00:00 2001 From: Kari Date: Tue, 22 Sep 2015 11:15:32 -0700 Subject: [PATCH 43/72] Finished route and controller function for retrieving overdue movies. --- controllers/rentals.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index e568ae5..146abaa 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -51,16 +51,15 @@ var rentalsController = { }, rentals_overdue: function(req, callback) { - var column = req.query.order_by ? req.query.order_by : "customer_id"; var statement = "SELECT \ rentals.id, rentals.title, rentals.customer_id, rentals.name, \ rentals.checkout_date, rentals.due_date, rentals.return_date \ FROM movies, rentals \ WHERE rentals.movie_id = movies.id \ - AND movies.title LIKE '%" + title + "%' \ - AND rentals.return_date - ORDER BY " + column + " ASC;"; + AND rentals.due_date < date('now') \ + AND rentals.return_date IS NULL \ + ORDER BY rentals.due_date ASC;"; var db = new Database('db/development.db'); From 29a2163a3d3f34a75dbc9925f6a282ab18c7b608 Mon Sep 17 00:00:00 2001 From: Kari Date: Tue, 22 Sep 2015 12:10:17 -0700 Subject: [PATCH 44/72] Can now post a new rental record to our db. WIP on having it also update the movie's inventory count and the customer's account credit. --- controllers/rentals.js | 43 ++++++++++++++++++++++++++++++++++++++++++ routes/rentals.js | 11 +++++++++++ 2 files changed, 54 insertions(+) diff --git a/controllers/rentals.js b/controllers/rentals.js index 146abaa..6542b99 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -71,6 +71,49 @@ var rentalsController = { callback(err, json_result); }); + }, + + checkout_movie: function(req, callback) { + // creating a new rental record + // reducing inventory available for that movie -1 + // reducing customer's account credit by $3 + + // var statement = + // "INSERT INTO rentals (customer_id, name, movie_id, title, checkout_date, due_date, return_date) \ + // VALUES (" + req.params.customer_id + ", " + CUSTOMER_NAME + ", " + req.params.movie_id + // + ", " + MOVIE_TITLE + ", date('now'), date('now', '+7 days', NULL); \ + + // UPDATE movies SET inventory_avail = inventory_avail - 1 WHERE ID = " + req.params.movie_id + "; \ + // UPDATE customers SET account_credit = account_credit - 3 WHERE ID = " + req.params.customer_id + ";"; + + var customer_id = parseInt(req.params.customer_id); + var movie_id = parseInt(req.params.movie_id); + + var statement = + "INSERT INTO rentals (customer_id, name, movie_id, title, checkout_date, due_date, return_date) \ + VALUES (" + customer_id + ", 'test customer name', " + movie_id + ", 'test movie name', date('now'), date('now', '+7 days'), NULL);"; + // UPDATE movies SET inventory_avail = inventory_avail - 1 WHERE ID = " + req.params.movie_id + "; \ + // UPDATE customers SET account_credit = account_credit - 3 WHERE ID = " + req.params.customer_id + "; \ + // SELECT rentals.id, rentals.title, rentals.customer_id, rentals.name, \ + // rentals.checkout_date, rentals.due_date, rentals.return_date \ + // FROM movies, rentals \ + // ORDER BY id DESC \ + // LIMIT 1"; + + + var db = new Database('db/development.db'); + db.query(statement, function(err, result) { + + console.log(statement); + console.log(err); + + var json_result = { + rental: result + }; + + callback(err, json_result); + }); + } }; diff --git a/routes/rentals.js b/routes/rentals.js index a5fe349..69abbe2 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -24,4 +24,15 @@ router.get("/overdue", function(req, res, next) { }) }) +// "POST ./rentals/{:customer_id}/checkout/{:movie_id}" +router.post("/:customer_id/checkout/:movie_id", function(req, res, next) { + rentalsController.checkout_movie(req, function(err, result) { + if (err) { + res.status(500).json(err); + } else { + res.status(200).json(result); + } + }) +}) + module.exports = router; \ No newline at end of file From 47468de34733e03c4301eb7aecbcf89642f406cb Mon Sep 17 00:00:00 2001 From: Kari Date: Tue, 22 Sep 2015 15:28:40 -0700 Subject: [PATCH 45/72] Got the checkout_movie function to create a new rental record, update the movie inventory_avail and customer account_credit. We are having to use test movie.title and customer.name now though because we haven't figured out how to execute that many queries at once. Working on that next. --- controllers/rentals.js | 48 ++++++++++++++++++------------------------ database.js | 14 ++++++++++++ 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index 6542b99..48f6746 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -74,47 +74,39 @@ var rentalsController = { }, checkout_movie: function(req, callback) { - // creating a new rental record - // reducing inventory available for that movie -1 - // reducing customer's account credit by $3 - - // var statement = - // "INSERT INTO rentals (customer_id, name, movie_id, title, checkout_date, due_date, return_date) \ - // VALUES (" + req.params.customer_id + ", " + CUSTOMER_NAME + ", " + req.params.movie_id - // + ", " + MOVIE_TITLE + ", date('now'), date('now', '+7 days', NULL); \ - - // UPDATE movies SET inventory_avail = inventory_avail - 1 WHERE ID = " + req.params.movie_id + "; \ - // UPDATE customers SET account_credit = account_credit - 3 WHERE ID = " + req.params.customer_id + ";"; - var customer_id = parseInt(req.params.customer_id); var movie_id = parseInt(req.params.movie_id); - var statement = + var post_rental_statement = "INSERT INTO rentals (customer_id, name, movie_id, title, checkout_date, due_date, return_date) \ - VALUES (" + customer_id + ", 'test customer name', " + movie_id + ", 'test movie name', date('now'), date('now', '+7 days'), NULL);"; - // UPDATE movies SET inventory_avail = inventory_avail - 1 WHERE ID = " + req.params.movie_id + "; \ - // UPDATE customers SET account_credit = account_credit - 3 WHERE ID = " + req.params.customer_id + "; \ - // SELECT rentals.id, rentals.title, rentals.customer_id, rentals.name, \ - // rentals.checkout_date, rentals.due_date, rentals.return_date \ - // FROM movies, rentals \ - // ORDER BY id DESC \ - // LIMIT 1"; - + VALUES (" + customer_id + ", 'test customer name', " + movie_id + ", 'test movie name', date('now'), date('now', '+7 days'), NULL); \ + UPDATE movies SET inventory_avail = inventory_avail - 1 WHERE ID = " + movie_id + "; \ + UPDATE customers SET account_credit = account_credit - 3 WHERE ID = " + customer_id + ";"; - var db = new Database('db/development.db'); - db.query(statement, function(err, result) { + var select_last_rental_statement = + "SELECT rentals.id, rentals.title, rentals.customer_id, rentals.name, rentals.checkout_date, rentals.due_date, rentals.return_date \ + FROM movies, rentals \ + ORDER BY rentals.id DESC \ + LIMIT 1"; - console.log(statement); - console.log(err); +// Test sql query +// INSERT INTO rentals (customer_id, name, movie_id, title, checkout_date, due_date, return_date) VALUES (2, 'test customer name', 12, 'test movie name', date('now'), date('now', '+7 days'), NULL); UPDATE movies SET inventory_avail = inventory_avail - 1 WHERE ID = 12; UPDATE customers SET account_credit = account_credit - 3 WHERE ID = 2; SELECT rentals.id, rentals.title, rentals.customer_id, rentals.name, rentals.checkout_date, rentals.due_date, rentals.return_date, movies.inventory_avail FROM movies, rentals ORDER BY rentals.id DESC LIMIT 1; + var db = new Database('db/development.db'); + + db.multi_query(post_rental_statement, function(err) { // no result, bc it's calling .exec (db.js file) + + db.query(select_last_rental_statement, function(err, result) { + var json_result = { rental: result }; - + callback(err, json_result); + }) }); - } + } // end of checkout_movie }; module.exports = rentalsController; diff --git a/database.js b/database.js index 7b3a587..247ce1c 100644 --- a/database.js +++ b/database.js @@ -20,7 +20,21 @@ StoreDatabase.prototype = { }); }); + }, + multi_query: function(statement, callback) { + var db = new sqlite3.Database(this.path); // creates a connection to the db + + db.serialize(function() { + // statement == some SQL string + db.exec(statement, function(err, result) { + // '.exec' does not give a result, so we don't need to pass it back into the callback() + if (callback) { callback(err); } + + db.close(); + }); + + }); } }; From 2f7e6aab77266afd07d772138ecdc3c14f1b9dc6 Mon Sep 17 00:00:00 2001 From: Kari Date: Tue, 22 Sep 2015 15:52:45 -0700 Subject: [PATCH 46/72] Fixed post route for checkout_movie, which will pull in the customer's name and movie's title before making the rental insert. --- controllers/rentals.js | 47 ++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index 48f6746..333bde1 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -77,11 +77,7 @@ var rentalsController = { var customer_id = parseInt(req.params.customer_id); var movie_id = parseInt(req.params.movie_id); - var post_rental_statement = - "INSERT INTO rentals (customer_id, name, movie_id, title, checkout_date, due_date, return_date) \ - VALUES (" + customer_id + ", 'test customer name', " + movie_id + ", 'test movie name', date('now'), date('now', '+7 days'), NULL); \ - UPDATE movies SET inventory_avail = inventory_avail - 1 WHERE ID = " + movie_id + "; \ - UPDATE customers SET account_credit = account_credit - 3 WHERE ID = " + customer_id + ";"; + var select_name_and_title = "SELECT name, title FROM customers, movies WHERE customers.id = " + customer_id + " AND movies.id = " + movie_id + ";"; var select_last_rental_statement = "SELECT rentals.id, rentals.title, rentals.customer_id, rentals.name, rentals.checkout_date, rentals.due_date, rentals.return_date \ @@ -89,22 +85,33 @@ var rentalsController = { ORDER BY rentals.id DESC \ LIMIT 1"; -// Test sql query -// INSERT INTO rentals (customer_id, name, movie_id, title, checkout_date, due_date, return_date) VALUES (2, 'test customer name', 12, 'test movie name', date('now'), date('now', '+7 days'), NULL); UPDATE movies SET inventory_avail = inventory_avail - 1 WHERE ID = 12; UPDATE customers SET account_credit = account_credit - 3 WHERE ID = 2; SELECT rentals.id, rentals.title, rentals.customer_id, rentals.name, rentals.checkout_date, rentals.due_date, rentals.return_date, movies.inventory_avail FROM movies, rentals ORDER BY rentals.id DESC LIMIT 1; - var db = new Database('db/development.db'); - - db.multi_query(post_rental_statement, function(err) { // no result, bc it's calling .exec (db.js file) - - db.query(select_last_rental_statement, function(err, result) { - - var json_result = { - rental: result - }; - - callback(err, json_result); - }) - }); + + db.query(select_name_and_title, function(err, result) { + var customer_name = result[0].name; + var movie_title = result[0].title; + console.log("typeof :", typeof customer_name); + + var post_rental_statement = + "INSERT INTO rentals (customer_id, name, movie_id, title, checkout_date, due_date, return_date) \ + VALUES (" + customer_id + ", '" + customer_name + "', " + movie_id + ", '" + movie_title + "', date('now'), date('now', '+7 days'), NULL); \ + UPDATE movies SET inventory_avail = inventory_avail - 1 WHERE ID = " + movie_id + "; \ + UPDATE customers SET account_credit = account_credit - 3 WHERE ID = " + customer_id + ";"; + + db.multi_query(post_rental_statement, function(err) { // no result, bc it's calling .exec (db.js file) + console.log("statment:", post_rental_statement); + console.log("error: ", err); + + db.query(select_last_rental_statement, function(err, result) { + + var json_result = { + rental: result + }; + + callback(err, json_result); + }) + }); + }) } // end of checkout_movie }; From a4defaf0e309c3218f976eb76147961cb1bc23a3 Mon Sep 17 00:00:00 2001 From: Kari Date: Tue, 22 Sep 2015 16:15:05 -0700 Subject: [PATCH 47/72] Wrote return_movie route and function which will update the movie's inventory +1 and will update the rental record with a return_date of now. --- controllers/rentals.js | 32 +++++++++++++++++++++++++++++--- routes/rentals.js | 11 +++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index 333bde1..d08b08a 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -99,8 +99,6 @@ var rentalsController = { UPDATE customers SET account_credit = account_credit - 3 WHERE ID = " + customer_id + ";"; db.multi_query(post_rental_statement, function(err) { // no result, bc it's calling .exec (db.js file) - console.log("statment:", post_rental_statement); - console.log("error: ", err); db.query(select_last_rental_statement, function(err, result) { @@ -112,8 +110,36 @@ var rentalsController = { }) }); }) + }, // end of checkout_movie - } // end of checkout_movie + return_movie: function(req, callback) { + var customer_id = parseInt(req.params.customer_id); + var movie_id = parseInt(req.params.movie_id); + + var return_movie_statement = + "UPDATE rentals SET return_date = date('now') WHERE movie_id = " + movie_id + " AND return_date IS NULL; \ + UPDATE movies SET inventory_avail = inventory_avail + 1 WHERE id = " + movie_id + ";"; + + var select_last_rental_statement = + "SELECT rentals.id, rentals.title, rentals.customer_id, rentals.name, rentals.checkout_date, rentals.due_date, rentals.return_date \ + FROM rentals \ + WHERE movie_id = " + movie_id + " AND customer_id = " + customer_id + ";"; + + var db = new Database('db/development.db'); + + + db.multi_query(return_movie_statement, function(err) { + db.query(select_last_rental_statement, function(err, result) { + console.log("error: ", err); + + var json_result = { + rental: result + }; + + callback(err, json_result); + }) + }) + } // end of return_movie }; module.exports = rentalsController; diff --git a/routes/rentals.js b/routes/rentals.js index 69abbe2..0530815 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -35,4 +35,15 @@ router.post("/:customer_id/checkout/:movie_id", function(req, res, next) { }) }) +// "PUT ./rentals/{:customer_id}/return/{:movie_id}" +router.put("/:customer_id/return/:movie_id", function(req, res, next) { + rentalsController.return_movie(req, function(err, result) { + if (err) { + res.status(500).json(err); + } else { + res.status(200).json(result); + } + }) +}) + module.exports = router; \ No newline at end of file From e35c49b617fba0d103f5af354214e2a05c825165 Mon Sep 17 00:00:00 2001 From: Kari Date: Tue, 22 Sep 2015 16:17:57 -0700 Subject: [PATCH 48/72] Added order by return date desc order for a customer's rental return history. --- controllers/rentals.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index d08b08a..6547703 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -123,7 +123,8 @@ var rentalsController = { var select_last_rental_statement = "SELECT rentals.id, rentals.title, rentals.customer_id, rentals.name, rentals.checkout_date, rentals.due_date, rentals.return_date \ FROM rentals \ - WHERE movie_id = " + movie_id + " AND customer_id = " + customer_id + ";"; + WHERE movie_id = " + movie_id + " AND customer_id = " + customer_id + " \ + ORDER BY return_date DESC;"; var db = new Database('db/development.db'); From 1a5a5958681457720ae3f146bcfacb406c5d9845 Mon Sep 17 00:00:00 2001 From: Kari Date: Tue, 22 Sep 2015 16:19:14 -0700 Subject: [PATCH 49/72] Updated json key to reflect that there could be multiple rental results returned. Now called rental_history instead of just rental. --- controllers/rentals.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index 6547703..33d3d0c 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -134,7 +134,7 @@ var rentalsController = { console.log("error: ", err); var json_result = { - rental: result + rental_history: result }; callback(err, json_result); From d6bc6f87c20a0d98e82666e26bab97b3ed8aeff2 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Tue, 22 Sep 2015 16:36:05 -0700 Subject: [PATCH 50/72] WIP: Updating the endpoint documentation as needed. --- endpoints.md | 144 ++++++++++++++++----------------------------------- 1 file changed, 44 insertions(+), 100 deletions(-) diff --git a/endpoints.md b/endpoints.md index 0718c2a..aebe6ed 100644 --- a/endpoints.md +++ b/endpoints.md @@ -14,8 +14,8 @@ __Request Parameters__ | Query Parameter | Value | | :-------------- | :------------- | | `order_by ` | _Optional._ Provide this parameter if you would like the customers sorted. Options include: `name`, `registered_at`, or `postal_code`. When using `name`, customers are sorted by their first name. | -| `number` | An integer that represents the number of customer records you'd like returned. | -| `page` | _Requires `number` query._ The page of customer records you'd like returned. | +| `number` | _Optional._ An integer that represents the number of customer records you'd like returned. | +| `page` | _Optional, but requires the `number` query._ The page of customer records you'd like returned. | __Response Format__ @@ -51,14 +51,8 @@ __Response Format__ __Endpoint__ `GET /customers/{:id}` - all of the attr of that customer - currently checked out movies - all movies with that customer_id and return_date == nil - include id, title - movies checked out in the past - all movies with that customer_id and return_date != nil (sort ASC by checkout_date) - include id, title and return_date +Returns all the information on record of the selected customer, including all the movies they have currently and previously checked out. __Request Parameter__ @@ -108,16 +102,16 @@ __Response__ __Endpoint__ `GET ./movies` -Returns all of the movies in our database with their complete information. -returns n number of movies (hardcoded?) sorted by title -offset by p records (hardcoded) +Returns all of the movies in our database with their complete information. Can be ordered by `title` or `release_date`. Also can be paginated with number and page (e.g. display the 2nd page of 20 customer records: `./movies?number=20&page=2`). __Request Parameters__ | Query Parameter | Value | | :-------------------| :------------- | | `order_by` | _Optional._ Provide this parameter if you would like the customers sorted. Options include: `title` or `release_date`. | +| `number` | _Optional._ An integer that represents the number of customer records you'd like returned. | +| `page` | _Optional, but requires the `number` query._ The page of customer records you'd like returned. | __Response__ @@ -146,15 +140,16 @@ __Response__ *** __Endpoint__ -`GET ./movies/{:title}` -Returns movies that match the title query. -E.g. ".movie/jaws", "./movie/north%20by%20northwest" +`GET ./movies/title/{:title}` + +Returns movies that fuzzy match the title query. The results are automatically ordered by `movie_id` but can also be ordered by title or release date. __Request Parameters__ | Path Parameter | Value | | :------------------| :------------------------| | `title` | The title of the movie. | +| `order_by` | _Optional._ Provide this parameter if you would like the customers sorted. Options include: `title` or `release_date`. | __Response__ @@ -171,8 +166,9 @@ __Response__ *** __Endpoint__ -`GET /movie/{:title}/customers` -default is sorting by id +`GET /movies/{:title}/rentals` + +Retrieve customers who currently and previously checked out a specific movie. Default ordering is by customer ID, but can be changed to order by the customer's name or the movie's checkout date. __Request Parameters__ @@ -182,57 +178,27 @@ __Request Parameters__ | Query Parameter | Value | | :------------------| :----------------------- | -| `order_by` | _Optional._ Provide this parameter if you would like the customers sorted. Options include: `name` or `checkout_date`. | +| `order_by` | _Optional._ Provide this parameter if you would like the customers sorted. Options include: `customer_id`, `name`, or `checkout_date`. | __Response__ { - "current_customers": [ + "current_rentals": [ { - "id": "5", - "name": "Aquila Riddle", - "registered_at": "Thu, 27 Aug 2015 08:17:24 -0700", - "address": "Ap #187-9582 Primis St.", - "city": "Tacoma", - "state": "WA", - "postal_code": "73251", - "phone": "(925) 161-2223", - "account_credit": 17.82 + "rental_id": "5", + "movie_title": "Night of the Living Dead", }, { - "id": "6", - "name": "Phyllis Russell", - "registered_at": "Wed, 02 Apr 2014 21:44:46 -0700", - "address": "746-8511 Ipsum Ave", - "city": "Boise", - "state": "Idaho", - "postal_code": "76759", - "phone": "(961) 964-5158", - "account_credit": 88.67 + } ], - "previous_customers": [ + + "previous_rentals": [ { - "id": "9", - "name": "Jacqueline Perry", - "registered_at": "Thu, 23 Jul 2015 10:18:35 -0700", - "address": "Ap #288-7228 Dis Rd.", - "city": "Anchorage", - "state": "AK", - "postal_code": "99789", - "phone": "(479) 207-8414", - "account_credit": 96.28 + }, { - "id": "5", - "name": "Aquila Riddle", - "registered_at": "Thu, 27 Aug 2015 08:17:24 -0700", - "address": "Ap #187-9582 Primis St.", - "city": "Tacoma", - "state": "WA", - "postal_code": "73251", - "phone": "(925) 161-2223", - "account_credit": 17.82 + }, … ] @@ -242,31 +208,28 @@ __Response__ ## Rentals __Endpoint__ -`POST /customers/{:id}/rental/{:title}` -maybe change it be searching for movie id instead of movie title? +`POST ./rentals/{:customer_id}/checkout/{:movie_id}` -Creates a new rental entry. - -PUT updates inventory_avail -1 for that movie - updates customer account_credit -$X rental fee +Checks out the given movie for the given customer, automatically setting the rental's return date to 7 days after checkout. __Request Parameters__ | Path Parameter | Value | | :---------------| :------------------------| -| `id` | The ID of the movie. | -| `title` | The title of the movie. | +| `customer_id` | The ID of the movie. | +| `movie_id` | The title of the movie. | __Response__ { - "1": { + "rental": { + "id": 2, "customer_id": "5", "name": "Aquila Riddle", "movie_id": "", "title": "Close Encounters of the Third Kind", - "checkout_date": "Thu, Sept 17 2015 16:26:30 -0700", - "due_date": "Fri, Sept 25 2015 00:00:00 -0700", + "checkout_date": "2015-09-13", + "due_date": "2015-09-20", "return_date": null } } @@ -274,28 +237,28 @@ __Response__ *** __Endpoint__ -`PUT /customers/{:id}/rental/{:title}` -updates return_date to Time.now (rental record) -updates inventory_avail +1 for that movie +`PUT ./rentals/{:customer_id}/return/{:movie_id}` + +Returns the updated rental information for that checked in movie and all previously returned movies in descending order of `return_date`. __Request Parameters__ | Path Parameter | Value | | :---------------| :------------------------| -| `id` | The ID of the movie. | -| `title` | The title of the movie. | +| `customer_id` | The ID of the movie. | +| `movie_id` | The title of the movie. | __Response__ { - "rental": { + "rental_history": { "customer_id": "5", "name": "Aquila Riddle", "movie_id": "", "title": "Close Encounters of the Third Kind", - "checkout_date": "Thu, Sept 17 2015 16:26:30 -0700", - "due_date": "Fri, Sept 25 2015 00:00:00 -0700", - "return_date": "Wed, Sept 23 2015 04:20:45 -0700" + "checkout_date": "2015-09-13", + "due_date": "2015-09-20", + "return_date": "2015-09-19" } } @@ -303,37 +266,18 @@ __Response__ __Endpoint__ `GET /rentals/overdue` -array of customers with all their overdue movies -overdue = current_date > due_date && return_date == nil + +Returns an array of rentals that are currently overdue. __Response__ { - "customers": [ + "overdue_movies": [ { - "id": "6", - "name" : "Phyllis Russell", - "overdue_movies": [ - { - "id": - "title" : "", - }, - { - "id": - "title" : "", - } - ] - }, + }, { - "id": "4", - "name" : "Carolyn Chandler", - "overdue_movies": [ - { - "id": - "title" : "", - } - ] + }, … ] From fa746e1755e012e8b2cb6e87b87a2414fa10d73d Mon Sep 17 00:00:00 2001 From: amirahaile Date: Tue, 22 Sep 2015 17:13:18 -0700 Subject: [PATCH 51/72] Installed supertest. --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 673e5ed..09835a2 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "private": true, "scripts": { "start": "node ./bin/www", + "test": "clear; DB=test mocha --recursive", "reset": "node ./utils/schema.js", "seed": "node ./utils/seeds.js" }, @@ -16,6 +17,7 @@ "mocha": "^2.3.2", "morgan": "~1.6.1", "serve-favicon": "~2.3.0", - "sqlite3": "^3.1.0" + "sqlite3": "^3.1.0", + "supertest": "^1.1.0" } } From 80bd426376ba92c75686a97faa6e3ca01e6945f5 Mon Sep 17 00:00:00 2001 From: amirahaile Date: Wed, 23 Sep 2015 07:59:06 -0700 Subject: [PATCH 52/72] WIP: Updated customers tests and started movies test. --- test/customer_controller_tests.js | 3 +- test/movies_controller_tests.js | 65 +++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 test/movies_controller_tests.js diff --git a/test/customer_controller_tests.js b/test/customer_controller_tests.js index d12d98f..629043f 100644 --- a/test/customer_controller_tests.js +++ b/test/customer_controller_tests.js @@ -1,4 +1,5 @@ var assert = require("assert"); +var sqlite3 = require('sqlite3').verbose(); var customersController = require("../controllers/customers"); describe("customersController", function() { @@ -31,4 +32,4 @@ describe("customersController", function() { }); }); -}) \ No newline at end of file +}) diff --git a/test/movies_controller_tests.js b/test/movies_controller_tests.js new file mode 100644 index 0000000..7cf6615 --- /dev/null +++ b/test/movies_controller_tests.js @@ -0,0 +1,65 @@ +var request = require('supertest'), + assert = require('assert'), + app = require('../app'), + sqlite3 = require('sqlite3').verbose(), + agent = request.agent(app); + +describe("/movies endpoints", function() { + beforeEach(function(done) { + db_cleaner = new sqlite3.Database('db/test.db'); + db_cleaner.serialize(function() { + db_cleaner.exec( + "BEGIN; \ + DELETE FROM movies; \ + INSERT INTO movies(title, overview, release_date, inventory_total, inventory_avail) \ + VALUES('Bring It On', 'Cheerleaders duel it out.', '2000-08-22', 10, 10), \ + ('Maws', 'Worm!', '2010-02-11', 11, 11); \ + COMMIT;" + , function(err) { + db_cleaner.close(); + done(); + } + ); + }); + }) + + describe("GET /", function() { + var movie_request, movie_request_title, movie_request_date; + + beforeEach(function(done) { + movie_request = agent.get('/movies').set('Accept', 'application/json'); + movie_request_title = agent.get('/movies?order_by=title').set('Accept', 'application/json'); + movie_request_date = agent.get('/movies?order_by=date').set('Accept', 'application/json'); + done(); + }) + + it("responds with json", function(done) { + movie_request + .expect('Content-Type', /application\/json/) + .expect(200, done); + }) + + it("returns an array of movie objects", function(done) { + movie_request.expect(200, function(error, result) { + assert.equal(result.body.length, 2); //the db_cleaner inserted 2 records + + var keys = ['id', 'title', 'overview', 'release_date', 'inventory_total', 'inventory_avail']; + assert.deepEqual(Object.keys(result.body[0]), keys); + done(); + }) + }) + + it("can be ordered by title", function(done) { + movie_request_title.expect(200, function(error, result) { + assert.equal(result.body[0].title, "Bring It On"); + assert.equal(result.body[1].title, "Maws"); + done(); + }) + }) + + // it("can be ordered by release_date") + + // also can limit number of returned records + // pagination + }) +}) From a18572480a9328bc69be8fedd43f2c26d1bbe1ad Mon Sep 17 00:00:00 2001 From: amirahaile Date: Wed, 23 Sep 2015 07:59:20 -0700 Subject: [PATCH 53/72] WIP: Created rentals test file. --- test/rentals_controllers_tests.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/rentals_controllers_tests.js diff --git a/test/rentals_controllers_tests.js b/test/rentals_controllers_tests.js new file mode 100644 index 0000000..e69de29 From 07b8a01805102b3256baa7215f704ee85b61c50f Mon Sep 17 00:00:00 2001 From: Kari Date: Wed, 23 Sep 2015 16:26:08 -0700 Subject: [PATCH 54/72] Added db/test.db to our gitignore and included a note in our Readme to tell future users how to setup their test db before running our tests. --- .gitignore | 1 + README.md | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/.gitignore b/.gitignore index ef063ee..fe51cc4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .DS_Store node_modules/ db/development.db +db/test.db diff --git a/README.md b/README.md index 2137413..9ecdd45 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,15 @@ Kari & Amira # Project: VideoStoreAPI +##Testing +To run our test base, you will need to setup your local test.db file with: +$ DB=test npm reset + +Then you can run our tests with: +$ npm test + +##Description + The overall goal of this project is to create a system that a video store (remember those?) could use to track their inventory of rental videos and their collection of customers. We will use [NodeJS](https://nodejs.org/en/) to construct a RESTful API. The goal of this API is to quickly serve information about the store's video collection, customer information, and to update rental status. This repository provides two JSON datafiles to serve as the initial seeds for this system. From 8644a3c88d23d0263976c7ea495f5aec4d650045 Mon Sep 17 00:00:00 2001 From: Kari Date: Wed, 23 Sep 2015 16:28:20 -0700 Subject: [PATCH 55/72] Removed db/test.db from git tracking --- db/test.db | Bin 2048 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 db/test.db diff --git a/db/test.db b/db/test.db deleted file mode 100644 index 21b1895594fafa32cf6f7e1b16d659eb17f49192..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2048 zcmWFz^vNtqRY=P(%1ta$FlJz3U}R))P*7lCU|`;40x zsEUz!9|I7Lg3%Bd4FRf!fCD3&xV$`LU`b+9PHJ*#aY=q|YEdzq!Q>p|>KNjx5aQ_M n0;3@?*h2sS6|5cj From 3b962f0d55b1b280e355fe69b684ac265448ae4c Mon Sep 17 00:00:00 2001 From: Kari Date: Wed, 23 Sep 2015 16:28:56 -0700 Subject: [PATCH 56/72] Updated instructions for setting up your test db file. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ecdd45..05737f4 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Kari & Amira ##Testing To run our test base, you will need to setup your local test.db file with: -$ DB=test npm reset +$ DB=test npm run reset Then you can run our tests with: $ npm test From 3acf51fd06a275ef9099a12a10948c74cf70de1c Mon Sep 17 00:00:00 2001 From: Kari Date: Wed, 23 Sep 2015 16:29:53 -0700 Subject: [PATCH 57/72] Changed db variable to be assigned a file path based on your env so that it uses a different db when testing vs during development. --- controllers/customers.js | 10 +++++----- controllers/movies.js | 6 ++++-- controllers/rentals.js | 17 ++++++++++------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index f2775c3..d0c1d3b 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -3,9 +3,6 @@ var Database = require('../database'); // Node module; Pulling in db object we made in a dif file var customersController = { - - // maybe move the var db = ... out here? - // ALL CUSTOMERS SEARCH... "/customers?order_by=name" // PAGINATION... "/customers?number=25&page=2" => customers 26-50 all_customers: function(req, callback) { @@ -19,7 +16,8 @@ var customersController = { var statement = "SELECT * FROM customers ORDER BY " + column + " ASC;"; } - var db = new Database('db/development.db'); + var db_env = process.env.DB || 'development', + db = new Database('db/' + db_env + '.db'); db.query(statement, function(err, result) { @@ -34,7 +32,9 @@ var customersController = { customer: function(req, callback) { var statement = "SELECT * FROM customers, rentals WHERE customers.id = " + req.params.id + " AND rentals.customer_id = " + req.params.id + " ORDER BY rentals.checkout_date ASC;"; - var db = new Database('db/development.db'); + + var db_env = process.env.DB || 'development', + db = new Database('db/' + db_env + '.db'); db.query(statement, function(err, result) { diff --git a/controllers/movies.js b/controllers/movies.js index d9b72d0..26595f6 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -15,7 +15,8 @@ var moviesController = { var statement = "SELECT * FROM movies ORDER BY " + column + " ASC;"; } - var db = new Database('db/development.db'); + var db_env = process.env.DB || 'development', + db = new Database('db/' + db_env + '.db'); db.query(statement, function(err, result) { var json_result = { @@ -31,7 +32,8 @@ var moviesController = { var title = req.params.title var statement = "SELECT * FROM movies WHERE title LIKE '%" + title + "%' ORDER BY " + column + " ASC;"; - var db = new Database('db/development.db'); + var db_env = process.env.DB || 'development', + db = new Database('db/' + db_env + '.db'); db.query(statement, function(err, result) { diff --git a/controllers/rentals.js b/controllers/rentals.js index 33d3d0c..b34b663 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -15,7 +15,8 @@ var rentalsController = { WHERE rentals.movie_id = movies.id AND movies.title LIKE '%" + title + "%' \ ORDER BY " + column + " ASC;"; - var db = new Database('db/development.db'); + var db_env = process.env.DB || 'development', + db = new Database('db/' + db_env + '.db'); db.query(statement, function(err, result) { @@ -61,8 +62,9 @@ var rentalsController = { AND rentals.return_date IS NULL \ ORDER BY rentals.due_date ASC;"; - var db = new Database('db/development.db'); - + var db_env = process.env.DB || 'development', + db = new Database('db/' + db_env + '.db'); + db.query(statement, function(err, result) { var json_result = { @@ -85,8 +87,9 @@ var rentalsController = { ORDER BY rentals.id DESC \ LIMIT 1"; - var db = new Database('db/development.db'); - + var db_env = process.env.DB || 'development', + db = new Database('db/' + db_env + '.db'); + db.query(select_name_and_title, function(err, result) { var customer_name = result[0].name; var movie_title = result[0].title; @@ -126,8 +129,8 @@ var rentalsController = { WHERE movie_id = " + movie_id + " AND customer_id = " + customer_id + " \ ORDER BY return_date DESC;"; - var db = new Database('db/development.db'); - + var db_env = process.env.DB || 'development', + db = new Database('db/' + db_env + '.db'); db.multi_query(return_movie_statement, function(err) { db.query(select_last_rental_statement, function(err, result) { From 9d207ec685266a0f10ccdfa474b07c523719ce9b Mon Sep 17 00:00:00 2001 From: Kari Date: Wed, 23 Sep 2015 16:30:34 -0700 Subject: [PATCH 58/72] Wrote tests for customers controller endpoints. --- test/customer_controller_tests.js | 91 +++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 11 deletions(-) diff --git a/test/customer_controller_tests.js b/test/customer_controller_tests.js index 629043f..bcfbeb1 100644 --- a/test/customer_controller_tests.js +++ b/test/customer_controller_tests.js @@ -1,21 +1,35 @@ -var assert = require("assert"); -var sqlite3 = require('sqlite3').verbose(); -var customersController = require("../controllers/customers"); +var request = require('supertest'), + assert = require('assert'), + app = require('../app'), + sqlite3 = require('sqlite3').verbose(), + agent = request.agent(app); + customersController = require("../controllers/customers"); describe("customersController", function() { + var test_db; beforeEach(function(done) { - db_cleaner = new sqlite3.Database('db/test.db'); - db_cleaner.serialize(function() { - db_cleaner.exec( + test_db = new sqlite3.Database('db/test.db'); + + test_db.serialize(function() { + test_db.exec( "BEGIN; \ DELETE FROM customers; \ + DELETE FROM rentals; \ + DELETE FROM movies; \ INSERT INTO customers(name, registered_at, address, city, state, postal_code, phone, account_credit) \ VALUES('Sarah', 'Wed', 'Ipsum Rd', 'Seattle', 'WA', '12345', '(123) 123-4567', 25.15), \ ('Jane', 'Thurs', '123 St', 'San Jose', 'CA', '56789', '(345) 124-2984', 12.00); \ + INSERT INTO rentals(customer_id, name, movie_id, title, checkout_date, due_date, return_date) \ + VALUES(1, 'Sarah', 1, 'Movie 1', '2015-07-14', '2015-07-21', '2015-07-21'), \ + (1, 'Sarah', 2, 'Movie 2', '2015-07-16', '2015-07-23', '2015-07-19'), \ + (1, 'Sarah', 3, 'Movie 3', '2015-07-01', '2015-07-08', '2015-07-09'), \ + (2, 'Jane', 4, 'Movie 4', '2015-07-14', '2015-07-21', '2015-07-15'), \ + (2, 'Jane', 5, 'Movie 5', '2015-07-16', '2015-07-23', '2015-07-17'), \ + (2, 'Jane', 6, 'Movie 6', '2015-07-01', '2015-07-08', '2015-07-02'); \ COMMIT;" , function(err) { - db_cleaner.close(); + test_db.close(); done(); } ); @@ -26,10 +40,65 @@ describe("customersController", function() { assert.equal(typeof customersController.all_customers, "function"); }); - it("returns a json object", function(done) { - customersController.all_customers(req, function(err, result) { - assert(typeof result, "json"); - }); + describe('GET /', function() { + var customer_request; + + beforeEach(function(done) { + customer_request = agent.get('/customers').set('Accept', 'application/json'); + done(); + }) + + it('responds with json', function(done) { + customer_request + .expect('Content-type', /application\/json/) + .expect(200, done); + }) + + it('returns an array of customer objects', function(done) { + customer_request.expect(200, function(error, result) { + assert.equal(result.body.customers.length, 2); + + var keys = ['id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit']; + assert.deepEqual(Object.keys(result.body.customers[0]), keys); + + done(); + }) + }) + }) + + it("has a 'customer' property that is a function", function() { + assert.equal(typeof customersController.customer, "function"); }); + describe('GET /:id', function() { + var customer_request; + + beforeEach(function(done) { + customer_request = agent.get('/customers/2').set('Accept', 'application/json'); + done(); + }) + + it('responds with json', function(done) { + customer_request + .expect('Content-type', /application\/json/) + .expect(200, done); + }) + + it('finds the right customer record', function(done) { + customer_request.expect(200, function(error, result) { + assert.deepEqual(result.body.account.name, 'Jane'); + done(); + }) + }) + + it("includes the customer's rental history", function(done) { + customer_request.expect(200, function(error, result) { + assert.equal(result.body.rented.length, 3); + assert.deepEqual(result.body.rented[0].title, "Movie 6"); + done(); + }) + }) + + }) + }) From 3e96d4b217b85b04227fa09d8e23a5e7d8c109be Mon Sep 17 00:00:00 2001 From: Kari Date: Wed, 23 Sep 2015 16:52:18 -0700 Subject: [PATCH 59/72] Commented out WIP db test. --- test/database_tests.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/database_tests.js b/test/database_tests.js index a2718a2..c6c682a 100644 --- a/test/database_tests.js +++ b/test/database_tests.js @@ -21,21 +21,21 @@ describe("Database", function() { assert.equal(db.path, database_path); }); - describe("'query' function", function() { - before(function() { - // create a customers table - db.query("CREATE TABLE IF NOT EXISTS customers (name TEXT);"); - - // insert some customers - }); - - it("has a customers table", function(done) { - var table_exists = "SELECT count(*) AS table_count FROM sqlite_master WHERE type='table' AND name='customers'; "; - - db.query(table_exists, function(result) { - assert.equal(result[0].table_count, 1); - done(); - }); - }); + // describe("'query' function", function() { + // before(function() { + // // create a customers table + // db.query("CREATE TABLE IF NOT EXISTS customers (name TEXT);"); + + // // insert some customers + // }); + + // it("has a customers table", function(done) { + // var table_exists = "SELECT count(*) AS table_count FROM sqlite_master WHERE type='table' AND name='customers'; "; + + // db.query(table_exists, function(result) { + // assert.equal(result[0].table_count, 1); + // done(); + // }); + // }); }); }); \ No newline at end of file From 1a300607a554c0156ad86e7f3f8649b7fe6380ec Mon Sep 17 00:00:00 2001 From: Kari Date: Wed, 23 Sep 2015 21:16:18 -0700 Subject: [PATCH 60/72] Commented out final closing bracket. --- test/database_tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/database_tests.js b/test/database_tests.js index c6c682a..6054eff 100644 --- a/test/database_tests.js +++ b/test/database_tests.js @@ -37,5 +37,5 @@ describe("Database", function() { // done(); // }); // }); - }); + // }); }); \ No newline at end of file From 90b55a9d12d483142cbfcff8de0c817e43dd389e Mon Sep 17 00:00:00 2001 From: Kari Date: Wed, 23 Sep 2015 21:37:17 -0700 Subject: [PATCH 61/72] Wrote tests for movies controller all_movies endpoint. --- test/movies_controller_tests.js | 53 ++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/test/movies_controller_tests.js b/test/movies_controller_tests.js index 7cf6615..99b0255 100644 --- a/test/movies_controller_tests.js +++ b/test/movies_controller_tests.js @@ -5,18 +5,21 @@ var request = require('supertest'), agent = request.agent(app); describe("/movies endpoints", function() { + var test_db; + beforeEach(function(done) { - db_cleaner = new sqlite3.Database('db/test.db'); - db_cleaner.serialize(function() { - db_cleaner.exec( + test_db = new sqlite3.Database('db/test.db'); + + test_db.serialize(function() { + test_db.exec( "BEGIN; \ DELETE FROM movies; \ INSERT INTO movies(title, overview, release_date, inventory_total, inventory_avail) \ VALUES('Bring It On', 'Cheerleaders duel it out.', '2000-08-22', 10, 10), \ - ('Maws', 'Worm!', '2010-02-11', 11, 11); \ + ('Maws', 'Worm!', '1998-02-11', 11, 11); \ COMMIT;" , function(err) { - db_cleaner.close(); + test_db.close(); done(); } ); @@ -26,40 +29,54 @@ describe("/movies endpoints", function() { describe("GET /", function() { var movie_request, movie_request_title, movie_request_date; - beforeEach(function(done) { + it("responds with json", function(done) { movie_request = agent.get('/movies').set('Accept', 'application/json'); - movie_request_title = agent.get('/movies?order_by=title').set('Accept', 'application/json'); - movie_request_date = agent.get('/movies?order_by=date').set('Accept', 'application/json'); - done(); - }) - it("responds with json", function(done) { movie_request .expect('Content-Type', /application\/json/) .expect(200, done); }) it("returns an array of movie objects", function(done) { + movie_request = agent.get('/movies').set('Accept', 'application/json'); + movie_request.expect(200, function(error, result) { - assert.equal(result.body.length, 2); //the db_cleaner inserted 2 records + assert.equal(result.body.movies.length, 2); //the tesb_db inserted 2 records var keys = ['id', 'title', 'overview', 'release_date', 'inventory_total', 'inventory_avail']; - assert.deepEqual(Object.keys(result.body[0]), keys); + assert.deepEqual(Object.keys(result.body.movies[0]), keys); done(); }) }) it("can be ordered by title", function(done) { + movie_request_title = agent.get('/movies?order_by=title').set('Accept', 'application/json'); + movie_request_title.expect(200, function(error, result) { - assert.equal(result.body[0].title, "Bring It On"); - assert.equal(result.body[1].title, "Maws"); + assert.equal(result.body.movies[0].title, "Bring It On"); + assert.equal(result.body.movies[1].title, "Maws"); done(); }) }) - // it("can be ordered by release_date") + it("can be ordered by release_date", function(done) { + movie_request_date = agent.get('/movies?order_by=release_date').set('Accept', 'application/json'); - // also can limit number of returned records - // pagination + movie_request_date.expect(200, function(error, result) { + assert.equal(result.body.movies[0].release_date, "1998-02-11"); + assert.equal(result.body.movies[1].release_date, "2000-08-22"); + done(); + }) + }) + + it("can determine the number of returned records per page and which page is returned", function(done) { + movie_request = agent.get('/movies?number=1&page=2').set('Accept', 'application/json'); + + movie_request.expect(200, function(error, result) { + assert.equal(result.body.movies.length, 1); + assert.equal(result.body.movies[0].title, "Maws"); + done(); + }) + }) }) }) From f8eba26986caf8b85c1a3f3b6e73f811c1ada8bf Mon Sep 17 00:00:00 2001 From: Kari Date: Wed, 23 Sep 2015 23:02:04 -0700 Subject: [PATCH 62/72] Wrote tests for rest of movies controller endpoints. Removed unused movie endpoint. We moved checking rentals into the rentals controller. --- routes/movies.js | 11 ------ test/movies_controller_tests.js | 61 ++++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/routes/movies.js b/routes/movies.js index 12bfac0..5138245 100644 --- a/routes/movies.js +++ b/routes/movies.js @@ -24,15 +24,4 @@ router.get("/:title", function(req, res, next) { }) }) -// "GET ./movies/{:title}/rentals" -router.get("/:title/rentals", function(req, res, next) { - moviesController.movie_rentals(req, function(err, result) { - if (err) { - res.status(500).json(err); - } else { - res.status(200).json(result); - } - }) -}) - module.exports = router; diff --git a/test/movies_controller_tests.js b/test/movies_controller_tests.js index 99b0255..6cf1c29 100644 --- a/test/movies_controller_tests.js +++ b/test/movies_controller_tests.js @@ -14,9 +14,18 @@ describe("/movies endpoints", function() { test_db.exec( "BEGIN; \ DELETE FROM movies; \ + DELETE FROM rentals; \ INSERT INTO movies(title, overview, release_date, inventory_total, inventory_avail) \ VALUES('Bring It On', 'Cheerleaders duel it out.', '2000-08-22', 10, 10), \ - ('Maws', 'Worm!', '1998-02-11', 11, 11); \ + ('Maws', 'Worm!', '1998-02-11', 11, 11), \ + ('Bring It On 2', 'Moar cheerleaders', '1990-04-12', 12, 12); \ + INSERT INTO rentals(customer_id, name, movie_id, title, checkout_date, due_date, return_date) \ + VALUES(1, 'Sarah', 1, 'Bring It On', '2015-07-14', '2015-07-21', '2015-07-21'), \ + (1, 'Sarah', 2, 'Maws', '2015-07-16', '2015-07-23', '2015-07-19'), \ + (1, 'Sarah', 3, 'Bring It On 2', '2015-07-01', '2015-07-08', '2015-07-09'), \ + (2, 'Jane', 1, 'Bring It On', '2015-07-14', '2015-07-21', '2015-07-15'), \ + (2, 'Jane', 2, 'Maws', '2015-07-16', '2015-07-23', '2015-07-17'), \ + (2, 'Jane', 3, 'Bring It On 2', '2015-07-01', '2015-07-08', '2015-07-02'); \ COMMIT;" , function(err) { test_db.close(); @@ -41,7 +50,7 @@ describe("/movies endpoints", function() { movie_request = agent.get('/movies').set('Accept', 'application/json'); movie_request.expect(200, function(error, result) { - assert.equal(result.body.movies.length, 2); //the tesb_db inserted 2 records + assert.equal(result.body.movies.length, 3); //the tesb_db inserted 2 records var keys = ['id', 'title', 'overview', 'release_date', 'inventory_total', 'inventory_avail']; assert.deepEqual(Object.keys(result.body.movies[0]), keys); @@ -54,7 +63,8 @@ describe("/movies endpoints", function() { movie_request_title.expect(200, function(error, result) { assert.equal(result.body.movies[0].title, "Bring It On"); - assert.equal(result.body.movies[1].title, "Maws"); + assert.equal(result.body.movies[1].title, "Bring It On 2"); + assert.equal(result.body.movies[2].title, "Maws"); done(); }) }) @@ -63,8 +73,9 @@ describe("/movies endpoints", function() { movie_request_date = agent.get('/movies?order_by=release_date').set('Accept', 'application/json'); movie_request_date.expect(200, function(error, result) { - assert.equal(result.body.movies[0].release_date, "1998-02-11"); - assert.equal(result.body.movies[1].release_date, "2000-08-22"); + assert.equal(result.body.movies[0].release_date, "1990-04-12"); + assert.equal(result.body.movies[1].release_date, "1998-02-11"); + assert.equal(result.body.movies[2].release_date, "2000-08-22"); done(); }) }) @@ -79,4 +90,44 @@ describe("/movies endpoints", function() { }) }) }) + + describe('GET /:title', function() { + var movie_request; + + it("responds with json", function(done) { + movie_request = agent.get('/movies/maws').set('Accept', 'application/json'); + + movie_request + .expect('Content-Type', /application\/json/) + .expect(200, done); + }) + + it('can find a specific movie', function(done) { + movie_request = agent.get('/movies/maws').set('Accept', 'application/json'); + + movie_request.expect(200, function(error, result) { + assert.equal(result.body.movie[0].title, 'Maws'); + done(); + }) + }) + + it('returns all partial matches when searching by title', function(done) { + movie_request = agent.get('/movies/bring').set('Accept', 'application/json'); + + movie_request.expect(200, function(error, result) { + assert.equal(result.body.movie.length, 2); + done(); + }) + }) + + it('can order by other columns if there are multiple results', function(done) { + movie_request = agent.get('/movies/bring?order_by=release_date').set('Accept', 'application/json'); + + movie_request.expect(200, function(error, result) { + assert.equal(result.body.movie[0].title, "Bring It On 2"); + done(); + }) + }) + }) + }) From 69c0671eab2899d66d3ed9a4b6b871aba655c887 Mon Sep 17 00:00:00 2001 From: Kari Date: Wed, 23 Sep 2015 23:05:06 -0700 Subject: [PATCH 63/72] Updated movies endpoint info in endpoints.md file. --- endpoints.md | 48 ++++-------------------------------------------- 1 file changed, 4 insertions(+), 44 deletions(-) diff --git a/endpoints.md b/endpoints.md index aebe6ed..9c559cf 100644 --- a/endpoints.md +++ b/endpoints.md @@ -56,9 +56,9 @@ Returns all the information on record of the selected customer, including all th __Request Parameter__ - | Path Parameter | Value | - | :---------------| :----------------- | - | `id ` | The customer's ID. | +| Path Parameter | Value | +| :---------------| :----------------- | +| `id ` | The customer's ID. | __Response__ @@ -140,7 +140,7 @@ __Response__ *** __Endpoint__ -`GET ./movies/title/{:title}` +`GET ./movies/{:title}` Returns movies that fuzzy match the title query. The results are automatically ordered by `movie_id` but can also be ordered by title or release date. @@ -165,46 +165,6 @@ __Response__ *** -__Endpoint__ -`GET /movies/{:title}/rentals` - -Retrieve customers who currently and previously checked out a specific movie. Default ordering is by customer ID, but can be changed to order by the customer's name or the movie's checkout date. - -__Request Parameters__ - -| Path Parameter | Value | -| :------------------| :----------------------- | -| `title` | The title of the movie. | - -| Query Parameter | Value | -| :------------------| :----------------------- | -| `order_by` | _Optional._ Provide this parameter if you would like the customers sorted. Options include: `customer_id`, `name`, or `checkout_date`. | - -__Response__ - - { - "current_rentals": [ - { - "rental_id": "5", - "movie_title": "Night of the Living Dead", - }, - { - - } - ], - - "previous_rentals": [ - { - - }, - { - - }, - … - ] - } - - ## Rentals __Endpoint__ From a8d2a5c4bb3441a4a071fa0ec5e718b4e991b6a4 Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 24 Sep 2015 10:05:39 -0700 Subject: [PATCH 64/72] Added description of endpoint for getting rental history for a given movie. --- endpoints.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/endpoints.md b/endpoints.md index 9c559cf..bc2fbd7 100644 --- a/endpoints.md +++ b/endpoints.md @@ -170,7 +170,7 @@ __Response__ __Endpoint__ `POST ./rentals/{:customer_id}/checkout/{:movie_id}` -Checks out the given movie for the given customer, automatically setting the rental's return date to 7 days after checkout. +Checks out the given movie for the given customer, automatically setting the rental's return date to 7 days after checkout. It reduces that movie's inventory_avail by 1 and deducts a $3 rental fee from the customer's account_credit. __Request Parameters__ @@ -199,7 +199,7 @@ __Response__ __Endpoint__ `PUT ./rentals/{:customer_id}/return/{:movie_id}` -Returns the updated rental information for that checked in movie and all previously returned movies in descending order of `return_date`. +Returns the updated rental information for that checked in movie and that movie's previous rental history in descending order of `return_date`. __Request Parameters__ @@ -227,18 +227,74 @@ __Response__ __Endpoint__ `GET /rentals/overdue` -Returns an array of rentals that are currently overdue. +Returns an array of all rentals that are currently overdue. __Response__ { "overdue_movies": [ - { + { + "id": 3, + "title": "Frankenstein", + "customer_id": 1, + "name": "Shelley Rocha", + "checkout_date": "2014-09-19", + "due_date": "2014-09-26", + "return_date": null + }, + { + "id": 6, + "title": "The Night of the Hunter", + "customer_id": 2, + "name": "Curran Stout", + "checkout_date": "2014-09-19", + "due_date": "2014-09-26", + "return_date": null + }, + … + ] + } + +*** +__Endpoint__ +`GET /rentals/title/{:title}` + +Returns an array of the given movie's rental history, grouping them in two sub arrays of 'current_rentals' and 'previous_rentals'. If there are multiple matched movies for the {:title} search, it will pull in all matching results. + +__Response__ + + { + "current_rentals": [ + { + "rental_id": 6, + "movie_title": "The Night of the Hunter", + "customer_id": 2, + "customer_name": "Curran Stout", + "checkout_date": "2014-09-19", + "due_date": "2014-09-26", + "return_date": null }, { - + "rental_id": 51, + "movie_title": "The Night of the Hunter", + "customer_id": 17, + "customer_name": "Ginger Heath", + "checkout_date": "2014-09-19", + "due_date": "2014-09-26", + "return_date": null + } + ], + "previous_rentals": [ + { + "rental_id": 17, + "movie_title": "The Night of the Hunter", + "customer_id": 6, + "customer_name": "Phyllis Russell", + "checkout_date": "2014-09-09", + "due_date": "2014-09-16", + "return_date": "2014-09-10" }, - … + ... ] } From 912a123c9a36ad526e8326d86679c46bd8d1b422 Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 24 Sep 2015 10:15:35 -0700 Subject: [PATCH 65/72] Removed console.logs --- controllers/rentals.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index b34b663..0ea05ec 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -93,7 +93,6 @@ var rentalsController = { db.query(select_name_and_title, function(err, result) { var customer_name = result[0].name; var movie_title = result[0].title; - console.log("typeof :", typeof customer_name); var post_rental_statement = "INSERT INTO rentals (customer_id, name, movie_id, title, checkout_date, due_date, return_date) \ @@ -134,7 +133,6 @@ var rentalsController = { db.multi_query(return_movie_statement, function(err) { db.query(select_last_rental_statement, function(err, result) { - console.log("error: ", err); var json_result = { rental_history: result From 73a4d0c9cc908ee13aa347323717b32371d76afc Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 24 Sep 2015 10:24:40 -0700 Subject: [PATCH 66/72] Updated endpoints.md file for clearer order. --- endpoints.md | 115 ++++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/endpoints.md b/endpoints.md index bc2fbd7..c3b0a15 100644 --- a/endpoints.md +++ b/endpoints.md @@ -167,63 +167,6 @@ __Response__ ## Rentals -__Endpoint__ -`POST ./rentals/{:customer_id}/checkout/{:movie_id}` - -Checks out the given movie for the given customer, automatically setting the rental's return date to 7 days after checkout. It reduces that movie's inventory_avail by 1 and deducts a $3 rental fee from the customer's account_credit. - -__Request Parameters__ - -| Path Parameter | Value | -| :---------------| :------------------------| -| `customer_id` | The ID of the movie. | -| `movie_id` | The title of the movie. | - -__Response__ - - { - "rental": { - "id": 2, - "customer_id": "5", - "name": "Aquila Riddle", - "movie_id": "", - "title": "Close Encounters of the Third Kind", - "checkout_date": "2015-09-13", - "due_date": "2015-09-20", - "return_date": null - } - } - -*** - -__Endpoint__ -`PUT ./rentals/{:customer_id}/return/{:movie_id}` - -Returns the updated rental information for that checked in movie and that movie's previous rental history in descending order of `return_date`. - -__Request Parameters__ - -| Path Parameter | Value | -| :---------------| :------------------------| -| `customer_id` | The ID of the movie. | -| `movie_id` | The title of the movie. | - -__Response__ - - { - "rental_history": { - "customer_id": "5", - "name": "Aquila Riddle", - "movie_id": "", - "title": "Close Encounters of the Third Kind", - "checkout_date": "2015-09-13", - "due_date": "2015-09-20", - "return_date": "2015-09-19" - } - } - -*** - __Endpoint__ `GET /rentals/overdue` @@ -298,3 +241,61 @@ __Response__ ... ] } + +*** + +__Endpoint__ +`POST ./rentals/{:customer_id}/checkout/{:movie_id}` + +Checks out the given movie for the given customer, automatically setting the rental's return date to 7 days after checkout. It reduces that movie's inventory_avail by 1 and deducts a $3 rental fee from the customer's account_credit. + +__Request Parameters__ + +| Path Parameter | Value | +| :---------------| :------------------------| +| `customer_id` | The ID of the movie. | +| `movie_id` | The title of the movie. | + +__Response__ + + { + "rental": { + "id": 2, + "customer_id": "5", + "name": "Aquila Riddle", + "movie_id": "", + "title": "Close Encounters of the Third Kind", + "checkout_date": "2015-09-13", + "due_date": "2015-09-20", + "return_date": null + } + } + +*** + +__Endpoint__ +`PUT ./rentals/{:customer_id}/return/{:movie_id}` + +Returns the updated rental information for that checked in movie and that movie's previous rental history in descending order of `return_date`. + +__Request Parameters__ + +| Path Parameter | Value | +| :---------------| :------------------------| +| `customer_id` | The ID of the movie. | +| `movie_id` | The title of the movie. | + +__Response__ + + { + "rental_history": { + "customer_id": "5", + "name": "Aquila Riddle", + "movie_id": "", + "title": "Close Encounters of the Third Kind", + "checkout_date": "2015-09-13", + "due_date": "2015-09-20", + "return_date": "2015-09-19" + } + } + From 77548813e9e3ebde16c278431faa11b2949271ee Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 24 Sep 2015 10:25:34 -0700 Subject: [PATCH 67/72] Wrote initial tests for rentals controller endpoints. --- test/rentals_controllers_tests.js | 163 ++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/test/rentals_controllers_tests.js b/test/rentals_controllers_tests.js index e69de29..db76700 100644 --- a/test/rentals_controllers_tests.js +++ b/test/rentals_controllers_tests.js @@ -0,0 +1,163 @@ +var request = require('supertest'), + assert = require('assert'), + app = require('../app'), + sqlite3 = require('sqlite3').verbose(), + agent = request.agent(app); + +describe("/rentals endpoints", function() { + var test_db; + + beforeEach(function(done) { + test_db = new sqlite3.Database('db/test.db'); + + test_db.serialize(function() { + test_db.exec( + "BEGIN; \ + DELETE FROM movies; \ + DELETE FROM rentals; \ + INSERT INTO movies(title, overview, release_date, inventory_total, inventory_avail) \ + VALUES('Bring It On', 'Cheerleaders duel it out.', '2000-08-22', 10, 10), \ + ('Maws', 'Worm!', '1998-02-11', 11, 11), \ + ('Bring It On 2', 'Moar cheerleaders', '1990-04-12', 12, 12); \ + INSERT INTO rentals(customer_id, name, movie_id, title, checkout_date, due_date, return_date) \ + VALUES(1, 'Sarah', 1, 'Bring It On', '2015-07-14', '2015-07-21', '2015-07-21'), \ + (1, 'Sarah', 2, 'Maws', '2015-07-16', '2015-07-23', '2015-07-19'), \ + (1, 'Sarah', 3, 'Bring It On 2', '2015-07-01', '2015-07-08', '2015-07-09'), \ + (2, 'Jane', 1, 'Bring It On', '2015-07-14', '2015-07-21', '2015-07-15'), \ + (2, 'Jane', 2, 'Maws', '2015-07-16', '2015-07-23', '2015-07-17'), \ + (2, 'Jane', 3, 'Bring It On 2', '2015-07-01', '2015-07-08', NULL); \ + COMMIT;" + , function(err) { + test_db.close(); + done(); + } + ); + }); + }) + + describe("GET /rentals/title/{:title}", function() { + var rental_request; + + it("responds with json", function(done) { + rental_request = agent.get('/rentals/title/maws').set('Accept', 'application/json'); + + rental_request + .expect('Content-Type', /application\/json/) + .expect(200, done); + }) + + it("returns an array of rental objects", function(done) { + rental_request = agent.get('/rentals/title/bring').set('Accept', 'application/json'); + + rental_request.expect(200, function(error, result) { + + var keys = ['rental_id', 'movie_title', 'customer_id', 'customer_name', 'checkout_date', 'due_date', 'return_date']; + assert.deepEqual(Object.keys(result.body.current_rentals[0]), keys); + done(); + }) + }) + + it('separates rental history into current and previous rentals', function(done) { + rental_request = agent.get('/rentals/title/bring').set('Accept', 'application/json'); + + rental_request.expect(200, function(error, result) { + assert.equal(result.body.current_rentals.length, 1); + assert.equal(result.body.previous_rentals.length, 3); + done(); + }) + }) + // it("can be ordered by title", function(done) { + // movie_request_title = agent.get('/movies?order_by=title').set('Accept', 'application/json'); + + // movie_request_title.expect(200, function(error, result) { + // assert.equal(result.body.movies[0].title, "Bring It On"); + // assert.equal(result.body.movies[1].title, "Bring It On 2"); + // assert.equal(result.body.movies[2].title, "Maws"); + // done(); + // }) + // }) + + // it("can be ordered by release_date", function(done) { + // movie_request_date = agent.get('/movies?order_by=release_date').set('Accept', 'application/json'); + + // movie_request_date.expect(200, function(error, result) { + // assert.equal(result.body.movies[0].release_date, "1990-04-12"); + // assert.equal(result.body.movies[1].release_date, "1998-02-11"); + // assert.equal(result.body.movies[2].release_date, "2000-08-22"); + // done(); + // }) + // }) + + // it("can determine the number of returned records per page and which page is returned", function(done) { + // movie_request = agent.get('/movies?number=1&page=2').set('Accept', 'application/json'); + + // movie_request.expect(200, function(error, result) { + // assert.equal(result.body.movies.length, 1); + // assert.equal(result.body.movies[0].title, "Maws"); + // done(); + // }) + // }) + }) + + describe('GET /rentals/overdue', function() { + var rental_request; + + it("responds with json", function(done) { + rental_request = agent.get('/rentals/overdue').set('Accept', 'application/json'); + + rental_request + .expect('Content-Type', /application\/json/) + .expect(200, done); + }) + + // it('can find a specific movie', function(done) { + // movie_request = agent.get('/movies/maws').set('Accept', 'application/json'); + + // movie_request.expect(200, function(error, result) { + // assert.equal(result.body.movie[0].title, 'Maws'); + // done(); + // }) + // }) + + // it('returns all partial matches when searching by title', function(done) { + // movie_request = agent.get('/movies/bring').set('Accept', 'application/json'); + + // movie_request.expect(200, function(error, result) { + // assert.equal(result.body.movie.length, 2); + // done(); + // }) + // }) + + // it('can order by other columns if there are multiple results', function(done) { + // movie_request = agent.get('/movies/bring?order_by=release_date').set('Accept', 'application/json'); + + // movie_request.expect(200, function(error, result) { + // assert.equal(result.body.movie[0].title, "Bring It On 2"); + // done(); + // }) + // }) + }) + + describe('POST ./rentals/{:customer_id}/checkout/{:movie_id}', function() { + + it("responds with json", function(done) { + rental_request = agent.post('/rentals/2/checkout/1').set('Accept', 'application/json'); + + rental_request + .expect('Content-Type', /application\/json/) + .expect(200, done); + }) + }) + + describe('PUT ./rentals/{:customer_id}/return/{:movie_id}', function() { + + it("responds with json", function(done) { + rental_request = agent.put('/rentals/2/return/3').set('Accept', 'application/json'); + + rental_request + .expect('Content-Type', /application\/json/) + .expect(200, done); + }) + }) + +}) From 365d52d5596bd6261acf8d1b17c5c005dfc5df4e Mon Sep 17 00:00:00 2001 From: Kari Date: Thu, 24 Sep 2015 10:53:13 -0700 Subject: [PATCH 68/72] Updated notes in endpoint.md file about GET /rentals/title/:title and finished writing tests for this endpoint. --- endpoints.md | 13 +++++++- test/rentals_controllers_tests.js | 49 +++++++++++++------------------ 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/endpoints.md b/endpoints.md index c3b0a15..ebd343e 100644 --- a/endpoints.md +++ b/endpoints.md @@ -203,7 +203,18 @@ __Response__ __Endpoint__ `GET /rentals/title/{:title}` -Returns an array of the given movie's rental history, grouping them in two sub arrays of 'current_rentals' and 'previous_rentals'. If there are multiple matched movies for the {:title} search, it will pull in all matching results. +Returns an array of the given movie's rental history, grouping them in two sub arrays of `current_rentals` and `previous_rentals`. + +If there are multiple matched movies for the {:title} search, it will pull in all matching results. + +The results are automatically ordered by `customer_id` but can also be ordered by `name` (customer's name), `checkout_date`, `due_date`, `return_date`. + +__Request Parameters__ + +| Path Parameter | Value | +| :------------------| :------------------------| +| `title` | The title of the movie. | +| `order_by` | _Optional._ Provide this parameter if you would like the rentals sorted. Options include: `name` (for customer name), `checkout_date`, `due_date`, or `return_date`. | __Response__ diff --git a/test/rentals_controllers_tests.js b/test/rentals_controllers_tests.js index db76700..24d809b 100644 --- a/test/rentals_controllers_tests.js +++ b/test/rentals_controllers_tests.js @@ -66,37 +66,28 @@ describe("/rentals endpoints", function() { done(); }) }) - // it("can be ordered by title", function(done) { - // movie_request_title = agent.get('/movies?order_by=title').set('Accept', 'application/json'); - - // movie_request_title.expect(200, function(error, result) { - // assert.equal(result.body.movies[0].title, "Bring It On"); - // assert.equal(result.body.movies[1].title, "Bring It On 2"); - // assert.equal(result.body.movies[2].title, "Maws"); - // done(); - // }) - // }) - - // it("can be ordered by release_date", function(done) { - // movie_request_date = agent.get('/movies?order_by=release_date').set('Accept', 'application/json'); - - // movie_request_date.expect(200, function(error, result) { - // assert.equal(result.body.movies[0].release_date, "1990-04-12"); - // assert.equal(result.body.movies[1].release_date, "1998-02-11"); - // assert.equal(result.body.movies[2].release_date, "2000-08-22"); - // done(); - // }) - // }) - // it("can determine the number of returned records per page and which page is returned", function(done) { - // movie_request = agent.get('/movies?number=1&page=2').set('Accept', 'application/json'); + it("can be ordered by name (customer's name)", function(done) { + rental_request = agent.get('/rentals/title/bring?order_by=name').set('Accept', 'application/json'); + + rental_request.expect(200, function(error, result) { + assert.equal(result.body.previous_rentals[0].customer_name, "Jane"); + assert.equal(result.body.previous_rentals[1].customer_name, "Sarah"); + assert.equal(result.body.previous_rentals[2].customer_name, "Sarah"); + done(); + }) + }) - // movie_request.expect(200, function(error, result) { - // assert.equal(result.body.movies.length, 1); - // assert.equal(result.body.movies[0].title, "Maws"); - // done(); - // }) - // }) + it("can be ordered by return_date", function(done) { + rental_request = agent.get('/rentals/title/bring?order_by=return_date').set('Accept', 'application/json'); + + rental_request.expect(200, function(error, result) { + assert.equal(result.body.previous_rentals[0].return_date, "2015-07-09"); + assert.equal(result.body.previous_rentals[1].return_date, "2015-07-15"); + assert.equal(result.body.previous_rentals[2].return_date, "2015-07-21"); + done(); + }) + }) }) describe('GET /rentals/overdue', function() { From 85fec22ef76dbb1e6a7f925b8a047e6e01f08a31 Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 25 Sep 2015 09:59:45 -0700 Subject: [PATCH 69/72] Wrote more tests for the rentals controller/endpoints. --- test/rentals_controllers_tests.js | 118 +++++++++++++++++++++++------- 1 file changed, 91 insertions(+), 27 deletions(-) diff --git a/test/rentals_controllers_tests.js b/test/rentals_controllers_tests.js index 24d809b..e595db8 100644 --- a/test/rentals_controllers_tests.js +++ b/test/rentals_controllers_tests.js @@ -25,7 +25,9 @@ describe("/rentals endpoints", function() { (1, 'Sarah', 3, 'Bring It On 2', '2015-07-01', '2015-07-08', '2015-07-09'), \ (2, 'Jane', 1, 'Bring It On', '2015-07-14', '2015-07-21', '2015-07-15'), \ (2, 'Jane', 2, 'Maws', '2015-07-16', '2015-07-23', '2015-07-17'), \ - (2, 'Jane', 3, 'Bring It On 2', '2015-07-01', '2015-07-08', NULL); \ + (2, 'Jane', 3, 'Bring It On 2', '2015-07-01', '2015-07-08', NULL), \ + (2, 'Jane', 2, 'Maws', '2015-07-01', '2015-10-08', NULL), \ + (1, 'Sarah', 2, 'Maws', '2015-07-01', '2015-07-08', '2015-07-10'); \ COMMIT;" , function(err) { test_db.close(); @@ -101,32 +103,24 @@ describe("/rentals endpoints", function() { .expect(200, done); }) - // it('can find a specific movie', function(done) { - // movie_request = agent.get('/movies/maws').set('Accept', 'application/json'); - - // movie_request.expect(200, function(error, result) { - // assert.equal(result.body.movie[0].title, 'Maws'); - // done(); - // }) - // }) - - // it('returns all partial matches when searching by title', function(done) { - // movie_request = agent.get('/movies/bring').set('Accept', 'application/json'); + it('returns an array of overdue rental records', function(done) { + rental_request = agent.get('/rentals/overdue').set('Accept', 'application/json'); - // movie_request.expect(200, function(error, result) { - // assert.equal(result.body.movie.length, 2); - // done(); - // }) - // }) + rental_request.expect(200, function(error, result) { + assert.equal(result.body.overdue_movies.length, 1); // only 1 seed record has no return_date and has a past due_date + assert.equal(result.body.overdue_movies[0].title, "Bring It On 2"); + done(); + }) + }) - // it('can order by other columns if there are multiple results', function(done) { - // movie_request = agent.get('/movies/bring?order_by=release_date').set('Accept', 'application/json'); + it('does not consider movies that have been returned late as still overdue', function(done) { + rental_request = agent.get('/rentals/overdue').set('Accept', 'application/json'); - // movie_request.expect(200, function(error, result) { - // assert.equal(result.body.movie[0].title, "Bring It On 2"); - // done(); - // }) - // }) + rental_request.expect(200, function(error, result) { + assert.notEqual(result.body.overdue_movies[0].name, "Sarah"); // Sarah returned a movie late + done(); + }) + }) }) describe('POST ./rentals/{:customer_id}/checkout/{:movie_id}', function() { @@ -137,18 +131,88 @@ describe("/rentals endpoints", function() { rental_request .expect('Content-Type', /application\/json/) .expect(200, done); - }) - }) + }) + + it('creates a new rental record and returns that rental record', function(done) { + rental_request = agent.post('/rentals/2/checkout/1').set('Accept', 'application/json'); + + rental_request.expect(200, function(error, result) { + + assert.equal(result.body.rental.length, 1); + assert.equal(result.body.rental[0].customer_id, 2); + done(); + }) + }) + + it("sets the checkout_date to be day('now')", function(done) { + rental_request = agent.post('/rentals/2/checkout/1').set('Accept', 'application/json'); + + rental_request.expect(200, function(error, result) { + var today = new Date; + var day = today.getDate(); + var month = today.getMonth() + 1; + var year = today.getFullYear(); + + if(day < 10) { day = '0' + day } + if(month < 10) { month = '0' + month } + + var now = year + "-" + month + "-" + day; + + assert.equal(result.body.rental[0].checkout_date, now); + done(); + }) + }) + + it("sets a due_date greater than today", function(done) { + rental_request = agent.post('/rentals/2/checkout/1').set('Accept', 'application/json'); + + rental_request.expect(200, function(error, result) { + var today = new Date; + var day = today.getDate(); + var month = today.getMonth() + 1; + var year = today.getFullYear(); + + if(day < 10) { day = '0' + day } + if(month < 10) { month = '0' + month } + + var now = year + "-" + month + "-" + day; + + assert(result.body.rental[0].due_date > now); + done(); + }) + }) + }); describe('PUT ./rentals/{:customer_id}/return/{:movie_id}', function() { it("responds with json", function(done) { - rental_request = agent.put('/rentals/2/return/3').set('Accept', 'application/json'); + rental_request = agent.put('/rentals/2/return/2').set('Accept', 'application/json'); rental_request .expect('Content-Type', /application\/json/) .expect(200, done); }) + + it("updates return_date to date('now') and returns the customer's rental history for that movie", function(done) { + rental_request = agent.put('/rentals/2/return/2').set('Accept', 'application/json'); + + rental_request.expect(200, function(error, result) { + var today = new Date; + var day = today.getDate(); + var month = today.getMonth() + 1; + var year = today.getFullYear(); + + if(day < 10) { day = '0' + day } + if(month < 10) { month = '0' + month } + + var now = year + "-" + month + "-" + day; + + assert.equal(result.body.rental_history.length, 2); + assert.equal(result.body.rental_history[0].customer_id, 2); + assert.equal(result.body.rental_history[0].return_date, now); + done(); + }) + }) }) }) From 860acdd7154b23fc7240290b865c420ad8f03cf8 Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 25 Sep 2015 10:00:42 -0700 Subject: [PATCH 70/72] Pulling in movie_id with rental results for easier data use cases later. --- controllers/rentals.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index 0ea05ec..b52ddb7 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -9,7 +9,7 @@ var rentalsController = { var title = req.params.title var statement = "SELECT \ - rentals.id, rentals.title, rentals.customer_id, rentals.name, \ + rentals.id, rentals.movie_id, rentals.title, rentals.customer_id, rentals.name, \ rentals.checkout_date, rentals.due_date, rentals.return_date \ FROM movies, rentals \ WHERE rentals.movie_id = movies.id AND movies.title LIKE '%" + title + "%' \ @@ -27,6 +27,7 @@ var rentalsController = { var rental = { rental_id: result[i].id, + movie_id: result[i].movie_id, movie_title: result[i].title, customer_id: result[i].customer_id, customer_name: result[i].name, @@ -119,11 +120,11 @@ var rentalsController = { var movie_id = parseInt(req.params.movie_id); var return_movie_statement = - "UPDATE rentals SET return_date = date('now') WHERE movie_id = " + movie_id + " AND return_date IS NULL; \ + "UPDATE rentals SET return_date = date('now') WHERE movie_id = " + movie_id + " AND return_date IS NULL AND customer_id = " + customer_id + "; \ UPDATE movies SET inventory_avail = inventory_avail + 1 WHERE id = " + movie_id + ";"; var select_last_rental_statement = - "SELECT rentals.id, rentals.title, rentals.customer_id, rentals.name, rentals.checkout_date, rentals.due_date, rentals.return_date \ + "SELECT rentals.id, rentals.movie_id, rentals.title, rentals.customer_id, rentals.name, rentals.checkout_date, rentals.due_date, rentals.return_date \ FROM rentals \ WHERE movie_id = " + movie_id + " AND customer_id = " + customer_id + " \ ORDER BY return_date DESC;"; From 1f3b158019ad1de877df0b19a93feec5ffa55416 Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 25 Sep 2015 10:01:15 -0700 Subject: [PATCH 71/72] Updated some json result formatting and descriptions to reflect our API's generated result data. --- endpoints.md | 80 +++++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/endpoints.md b/endpoints.md index ebd343e..cabe8d4 100644 --- a/endpoints.md +++ b/endpoints.md @@ -52,7 +52,7 @@ __Response Format__ __Endpoint__ `GET /customers/{:id}` -Returns all the information on record of the selected customer, including all the movies they have currently and previously checked out. +Returns all the information on record of the selected customer, including all the movies they have currently and previously checked out. Rental records are ordered by checkout_date. __Request Parameter__ @@ -67,34 +67,38 @@ __Response__ "id": 2, "name": "Curran Stout", "registered_at": "Wed, 16 Apr 2014 21:40: -0770" - "address": , - - "renting": [ - { - "id": 1 - "title": "Psycho", - "checkout_date": "", - "due_date": "" , - "return_date": null - }, - { - "id": 2 - "title": "Jaws", - "checkout_date": "", - "due_date": "", - "return_date": null - } - ], - "rented" : [ - { - "id": 8 - "title": "The French Connection", - "checkout_date": "", - "due_date": "", - "return_date": "" - } - ] - } + "address": "123 Street Road", + "city": "San Francisco", + "state": "CA", + "postal_code": "12345", + "phone": "(123) 123-1234", + "account_credit": "12.45" + }, + "renting": [ + { + "id": 1 + "title": "Psycho", + "checkout_date": "2014-09-19", + "due_date": "2014-09-26" , + "return_date": null + }, + { + "id": 2 + "title": "Jaws", + "checkout_date": "2015-09-19", + "due_date": "2015-09-26", + "return_date": null + } + ], + "rented" : [ + { + "id": 8 + "title": "The French Connection", + "checkout_date": "2015-01-03", + "due_date": "2015-01-10", + "return_date": "2015-01-09" + } + ] } @@ -142,7 +146,7 @@ __Response__ __Endpoint__ `GET ./movies/{:title}` -Returns movies that fuzzy match the title query. The results are automatically ordered by `movie_id` but can also be ordered by title or release date. +Returns movies that fuzzy match the title query. The results are automatically ordered by `movie_id` but can also be ordered by `title` or `release_date`. __Request Parameters__ @@ -154,12 +158,16 @@ __Request Parameters__ __Response__ { - "movies" : { + "movie" : [ + { + "id": 23, "title": "The Night of the Hunter", "overview": "Harry Powell marries and murders widows for their money, believing he is helping God do away with women who arouse men's carnal instincts. Arrested for auto theft, he shares a cell with condemned killer Ben Harper and tries to get him to reveal the whereabouts of the $10,000 he stole. Only Ben's nine-year-old son, John, and four-year-old daughter, Pearl, know the money is in Pearl's doll; and they have sworn to their father to keep this secret. After Ben is executed, Preacher goes to Cresap's Landing to court Ben's widow, Willa. When he overwhelms her with his Scripture quoting, sermons, and hymns, she agrees to marry him. On their wedding night, he tells her they will never have sex because it is sinful.", "release_date": "1955-07-26", - "inventory": 9 - } + "inventory_total": 9, + "inventory_avail": 7 + }, + ... ] } @@ -170,7 +178,7 @@ __Response__ __Endpoint__ `GET /rentals/overdue` -Returns an array of all rentals that are currently overdue. +Returns an array of all rentals that are currently overdue ordered ASC by `due_date`. Includes information about the customer associated with each rental. __Response__ @@ -205,7 +213,7 @@ __Endpoint__ Returns an array of the given movie's rental history, grouping them in two sub arrays of `current_rentals` and `previous_rentals`. -If there are multiple matched movies for the {:title} search, it will pull in all matching results. +If there are multiple matched movies for the `{:title}` search, it will pull in all matching results. The results are automatically ordered by `customer_id` but can also be ordered by `name` (customer's name), `checkout_date`, `due_date`, `return_date`. @@ -287,7 +295,7 @@ __Response__ __Endpoint__ `PUT ./rentals/{:customer_id}/return/{:movie_id}` -Returns the updated rental information for that checked in movie and that movie's previous rental history in descending order of `return_date`. +Returns the updated rental information for that checked in movie and that customer's previous rental history for that movie in descending order of `return_date`. __Request Parameters__ From aa047ee6a0a9ba4e5a119c6be70d4347c40688c7 Mon Sep 17 00:00:00 2001 From: Kari Date: Fri, 25 Sep 2015 10:03:40 -0700 Subject: [PATCH 72/72] Updated rentals test to include movie_id per the change in our rentals controller. --- test/rentals_controllers_tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rentals_controllers_tests.js b/test/rentals_controllers_tests.js index e595db8..fd1b58b 100644 --- a/test/rentals_controllers_tests.js +++ b/test/rentals_controllers_tests.js @@ -53,7 +53,7 @@ describe("/rentals endpoints", function() { rental_request.expect(200, function(error, result) { - var keys = ['rental_id', 'movie_title', 'customer_id', 'customer_name', 'checkout_date', 'due_date', 'return_date']; + var keys = ['rental_id', 'movie_id', 'movie_title', 'customer_id', 'customer_name', 'checkout_date', 'due_date', 'return_date']; assert.deepEqual(Object.keys(result.body.current_rentals[0]), keys); done(); })