From a11a00f15e276f5df59ba312690df1acc98c99c4 Mon Sep 17 00:00:00 2001 From: Jessica Date: Tue, 14 Jun 2016 14:37:14 -0700 Subject: [PATCH 01/93] created routes files, pseudocode and lib file --- app.js | 7 ++++++- lib/customers.js | 0 lib/movies.js | 0 lib/rentals.js | 0 routes/customers.js | 0 routes/movies.js | 0 routes/rentals.js | 0 7 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 lib/customers.js create mode 100644 lib/movies.js create mode 100644 lib/rentals.js create mode 100644 routes/customers.js create mode 100644 routes/movies.js create mode 100644 routes/rentals.js diff --git a/app.js b/app.js index f0579b1dc..4d54a1a11 100644 --- a/app.js +++ b/app.js @@ -21,7 +21,12 @@ app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); -app.use('/', routes); +var indexRoutes = require('./routes/index'); +// /zomg inside index route +app.use('/', indexRoutes); +// customers +// rentals +// movies // catch 404 and forward to error handler app.use(function(req, res, next) { diff --git a/lib/customers.js b/lib/customers.js new file mode 100644 index 000000000..e69de29bb diff --git a/lib/movies.js b/lib/movies.js new file mode 100644 index 000000000..e69de29bb diff --git a/lib/rentals.js b/lib/rentals.js new file mode 100644 index 000000000..e69de29bb diff --git a/routes/customers.js b/routes/customers.js new file mode 100644 index 000000000..e69de29bb diff --git a/routes/movies.js b/routes/movies.js new file mode 100644 index 000000000..e69de29bb diff --git a/routes/rentals.js b/routes/rentals.js new file mode 100644 index 000000000..e69de29bb From 991bd14fe2abde0e96adde93fd1abb52c898456e Mon Sep 17 00:00:00 2001 From: Jessica Date: Tue, 14 Jun 2016 14:46:01 -0700 Subject: [PATCH 02/93] pseudocoded all the routes. ALL OF THEM --- app.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app.js b/app.js index 4d54a1a11..754016bb2 100644 --- a/app.js +++ b/app.js @@ -25,8 +25,18 @@ var indexRoutes = require('./routes/index'); // /zomg inside index route app.use('/', indexRoutes); // customers +// GET +// POST - check-in and check-out +// needs id + // rentals +// GET +// title +// needs customer id, movie title + // movies +// GET +// needs title // catch 404 and forward to error handler app.use(function(req, res, next) { From 9e4894d9ecb647e8cee79f55abe2414aa46f85bc Mon Sep 17 00:00:00 2001 From: Jessica Date: Tue, 14 Jun 2016 14:47:47 -0700 Subject: [PATCH 03/93] semicolon destructiongit add . --- app.js | 59 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/app.js b/app.js index 754016bb2..950de31ac 100644 --- a/app.js +++ b/app.js @@ -1,29 +1,30 @@ -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 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 routes = require('./routes/index') -var app = express(); +var app = express() // view engine setup -app.set('views', path.join(__dirname, 'views')); -app.set('view engine', 'jade'); +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(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'))) -var indexRoutes = require('./routes/index'); +var indexRoutes = require('./routes/index') // /zomg inside index route -app.use('/', indexRoutes); +app.use('/', indexRoutes) +app.use('/zomg', indexRoutes) // customers // GET // POST - check-in and check-out @@ -40,10 +41,10 @@ app.use('/', indexRoutes); // catch 404 and forward to error handler app.use(function(req, res, next) { - var err = new Error('Not Found'); - err.status = 404; - next(err); -}); + var err = new Error('Not Found') + err.status = 404 + next(err) +}) // error handlers @@ -51,23 +52,23 @@ app.use(function(req, res, next) { // will print stacktrace if (app.get('env') === 'development') { app.use(function(err, req, res, next) { - res.status(err.status || 500); + 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.status(err.status || 500) res.render('error', { message: err.message, error: {} - }); -}); + }) +}) -module.exports = app; +module.exports = app From 36c5ab29dc4bb7fa2a1f87d55168bf31799aee02 Mon Sep 17 00:00:00 2001 From: Jessica Date: Tue, 14 Jun 2016 14:51:48 -0700 Subject: [PATCH 04/93] completed /zomg route, json is successful --- routes/index.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/routes/index.js b/routes/index.js index 06cfc1137..ad1b96002 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,9 +1,13 @@ -var express = require('express'); -var router = express.Router(); +var express = require('express') +var router = express.Router() /* GET home page. */ router.get('/', function(req, res, next) { res.status(200).json({whatevs: 'whatevs!!!'}) -}); +}) -module.exports = router; +router.get('/zomg', function(req, res) { + res.status(200).json({working: 'hell yeah it works!'}) +}) + +module.exports = router From da054887f42a930d3cf00d18a53bcd066ece3f10 Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 14 Jun 2016 15:12:28 -0700 Subject: [PATCH 05/93] Added an images folder and inside put our ERD --- public/images/VideoKilledTheRadioStar.png | Bin 0 -> 96414 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 public/images/VideoKilledTheRadioStar.png diff --git a/public/images/VideoKilledTheRadioStar.png b/public/images/VideoKilledTheRadioStar.png new file mode 100644 index 0000000000000000000000000000000000000000..b26a71c90cfbe5dbd8e066d04da2fe35ad8346e4 GIT binary patch literal 96414 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 IZx;0b0K7mwCIA2c literal 0 HcmV?d00001 From f8ba0ae43fec8457370ce1562e5ffd8048aa77d1 Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 14 Jun 2016 15:24:37 -0700 Subject: [PATCH 06/93] Added massive dependencies, added extra scripts for our database --- app.js | 13 +++++++++++-- package.json | 10 ++++++++-- tasks/load_schema.js | 12 ++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 tasks/load_schema.js diff --git a/app.js b/app.js index 950de31ac..2a7b2d9e5 100644 --- a/app.js +++ b/app.js @@ -4,11 +4,20 @@ 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 app = express() +var massive = require("massive"); +var connectionString = "postgres://localhost/video_store"; + +// connect to Massive and get the db instance. You can safely use the +// convenience sync method here because its on app load +// you can also use loadSync - it's an alias +var massiveInstance = massive.connectSync({connectionString : connectionString}) + +// Set a reference to the massive instance on Express' app: +app.set('db', massiveInstance); + // view engine setup app.set('views', path.join(__dirname, 'views')) app.set('view engine', 'jade') diff --git a/package.json b/package.json index d39b26403..52307576a 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,12 @@ "private": true, "scripts": { "start": "nodemon ./bin/www", - "test": "clear; jasmine-node --verbose spec/" + "test": "clear; jasmine-node --verbose spec/", + "db:drop": "dropdb video_store", + "db:create": "createdb video_store", + "db:schema": "node tasks/load_schema", + "db:seed": "", + "db:reset": "npm run db:drop; npm run db:create; npm run db:schema" }, "dependencies": { "body-parser": "~1.13.2", @@ -14,7 +19,8 @@ "jade": "~1.11.0", "morgan": "~1.6.1", "sequelize": "^3.23.3", - "serve-favicon": "~2.3.0" + "serve-favicon": "~2.3.0", + "massive": "^2.3.0" }, "devDependencies": { "jasmine-node": "^1.14.5", diff --git a/tasks/load_schema.js b/tasks/load_schema.js new file mode 100644 index 000000000..66271aa53 --- /dev/null +++ b/tasks/load_schema.js @@ -0,0 +1,12 @@ +var massive = require('massive'); +var connectionString = "postgres://localhost/video_store"; + +var db = massive.connectSync({connectionString : connectionString}); + +db.setup.schema([], function(err, res) { + if(err) { + throw(new Error(err.message)); + } + console.log("yay schema!"); + process.exit(); +}); From 2c42d48da8801dfaa61ea5f680c5b53f55d19d7c Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 14 Jun 2016 15:37:51 -0700 Subject: [PATCH 07/93] added load_schema with all database tables and what they will need. made sure table reference was correct for massive --- app.js | 6 +++--- db/setup/schema.sql | 30 ++++++++++++++++++++++++++++++ tasks/load_schema.js | 14 +++++++------- 3 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 db/setup/schema.sql diff --git a/app.js b/app.js index 2a7b2d9e5..55e4bb308 100644 --- a/app.js +++ b/app.js @@ -7,8 +7,8 @@ var bodyParser = require('body-parser') var routes = require('./routes/index') var app = express() -var massive = require("massive"); -var connectionString = "postgres://localhost/video_store"; +var massive = require("massive") +var connectionString = "postgres://localhost/video_store" // connect to Massive and get the db instance. You can safely use the // convenience sync method here because its on app load @@ -16,7 +16,7 @@ var connectionString = "postgres://localhost/video_store"; var massiveInstance = massive.connectSync({connectionString : connectionString}) // Set a reference to the massive instance on Express' app: -app.set('db', massiveInstance); +app.set('db', massiveInstance) // view engine setup app.set('views', path.join(__dirname, 'views')) diff --git a/db/setup/schema.sql b/db/setup/schema.sql new file mode 100644 index 000000000..dd79a0f5e --- /dev/null +++ b/db/setup/schema.sql @@ -0,0 +1,30 @@ +DROP TABLE IF EXISTS customers; +CREATE TABLE customers( + id serial PRIMARY KEY, + name text, + registered_at text, + address text, + city text, + state text, + postal_code text, + phone text, + account_credit numeric +); + +DROP TABLE IF EXISTS movies; +CREATE TABLE movies( + id serial PRIMARY KEY, + title text, + overview text, + release_date text, + inventory int +); + +DROP TABLE IF EXISTS rentals; +CREATE TABLE rentals( + id serial PRIMARY KEY, + customer_id int, + check_in boolean, + check_out boolean, + return_date datetime +); diff --git a/tasks/load_schema.js b/tasks/load_schema.js index 66271aa53..eb2e502f0 100644 --- a/tasks/load_schema.js +++ b/tasks/load_schema.js @@ -1,12 +1,12 @@ -var massive = require('massive'); -var connectionString = "postgres://localhost/video_store"; +var massive = require('massive') +var connectionString = "postgres://localhost/video_store" -var db = massive.connectSync({connectionString : connectionString}); +var db = massive.connectSync({connectionString : connectionString}) db.setup.schema([], function(err, res) { if(err) { - throw(new Error(err.message)); + throw(new Error(err.message)) } - console.log("yay schema!"); - process.exit(); -}); + console.log("yay schema!") + process.exit() +}) From 32edfb723b843c43c91e759d4f4ffa4499d42b59 Mon Sep 17 00:00:00 2001 From: Jessica Date: Wed, 15 Jun 2016 09:32:28 -0700 Subject: [PATCH 08/93] route for customers index created --- app.js | 2 ++ routes/customers.js | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/app.js b/app.js index 55e4bb308..af84fd3bd 100644 --- a/app.js +++ b/app.js @@ -36,6 +36,8 @@ app.use('/', indexRoutes) app.use('/zomg', indexRoutes) // customers // GET +var customerRoutes = require('./routes/customers') +app.use('/customers', customerRoutes) // POST - check-in and check-out // needs id diff --git a/routes/customers.js b/routes/customers.js index e69de29bb..db2a0c238 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -0,0 +1,16 @@ +var express = require('express') +var router = express.Router() + +router.get('/', function(req, res) { + res.json({customers: 'customers yaaaay'}) +}) + +// router.get('/customers', function(req, res, next) { +// res.status(200).json({customers: 'customers yaaaay!'}) +// }) + +// router.get('/zomg', function(req, res) { +// res.status(200).json({working: 'hell yeah it works!'}) +// }) + +module.exports = router \ No newline at end of file From cf26e9181534b4b0afe7da925f5c716dbaadad2e Mon Sep 17 00:00:00 2001 From: Jessica Date: Wed, 15 Jun 2016 09:34:39 -0700 Subject: [PATCH 09/93] movies index route created --- app.js | 2 ++ routes/customers.js | 8 -------- routes/index.js | 4 ---- routes/movies.js | 9 +++++++++ 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/app.js b/app.js index af84fd3bd..b1c105de1 100644 --- a/app.js +++ b/app.js @@ -48,6 +48,8 @@ app.use('/customers', customerRoutes) // movies // GET +var moviesRoutes = require('./routes/movies') +app.use('/movies', moviesRoutes) // needs title // catch 404 and forward to error handler diff --git a/routes/customers.js b/routes/customers.js index db2a0c238..62346dbb2 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -5,12 +5,4 @@ router.get('/', function(req, res) { res.json({customers: 'customers yaaaay'}) }) -// router.get('/customers', function(req, res, next) { -// res.status(200).json({customers: 'customers yaaaay!'}) -// }) - -// router.get('/zomg', function(req, res) { -// res.status(200).json({working: 'hell yeah it works!'}) -// }) - module.exports = router \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index ad1b96002..24bda7d04 100644 --- a/routes/index.js +++ b/routes/index.js @@ -6,8 +6,4 @@ router.get('/', function(req, res, next) { res.status(200).json({whatevs: 'whatevs!!!'}) }) -router.get('/zomg', function(req, res) { - res.status(200).json({working: 'hell yeah it works!'}) -}) - module.exports = router diff --git a/routes/movies.js b/routes/movies.js index e69de29bb..fedd37fb7 100644 --- a/routes/movies.js +++ b/routes/movies.js @@ -0,0 +1,9 @@ +var express = require('express') +var router = express.Router() + +/* GET home page. */ +router.get('/', function(req, res, next) { + res.status(200).json({movies: 'movies!!!'}) +}) + +module.exports = router From 9fc335ba908f45c48e478d7b990bef921f303cd5 Mon Sep 17 00:00:00 2001 From: Jessica Date: Wed, 15 Jun 2016 09:40:36 -0700 Subject: [PATCH 10/93] added rentals/:title route --- app.js | 2 ++ routes/rentals.js | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/app.js b/app.js index b1c105de1..fdc3590ac 100644 --- a/app.js +++ b/app.js @@ -43,6 +43,8 @@ app.use('/customers', customerRoutes) // rentals // GET +var rentalsRoutes = require('./routes/rentals') +app.use('/rentals', rentalsRoutes) // title // needs customer id, movie title diff --git a/routes/rentals.js b/routes/rentals.js index e69de29bb..f5a385416 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -0,0 +1,12 @@ +var express = require('express') +var router = express.Router() + +router.get('/', function(req, res) { + res.json({rentals: 'home for rentals!!'}) +}) + +router.get('/:title', function(req, res) { + res.json({rentals: 'rentals!!'}) +}) + +module.exports = router \ No newline at end of file From b9741f83a27ebb6079c60fd814655afc7798e38f Mon Sep 17 00:00:00 2001 From: Adriana Date: Wed, 15 Jun 2016 15:35:21 -0700 Subject: [PATCH 11/93] Added seeding data into database, changed schema for rentals to text, not datetime. Added a script for db:seed and changed db:reset. --- db/setup/schema.sql | 2 +- package.json | 4 ++-- tasks/seed.js | 20 ++++++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 tasks/seed.js diff --git a/db/setup/schema.sql b/db/setup/schema.sql index dd79a0f5e..558769f40 100644 --- a/db/setup/schema.sql +++ b/db/setup/schema.sql @@ -26,5 +26,5 @@ CREATE TABLE rentals( customer_id int, check_in boolean, check_out boolean, - return_date datetime + return_date text ); diff --git a/package.json b/package.json index 52307576a..a8be03a44 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ "db:drop": "dropdb video_store", "db:create": "createdb video_store", "db:schema": "node tasks/load_schema", - "db:seed": "", - "db:reset": "npm run db:drop; npm run db:create; npm run db:schema" + "db:seed": "node tasks/seed.js", + "db:reset": "npm run db:drop; npm run db:create; npm run db:schema; npm run db:seed;" }, "dependencies": { "body-parser": "~1.13.2", diff --git a/tasks/seed.js b/tasks/seed.js new file mode 100644 index 000000000..a89b2340c --- /dev/null +++ b/tasks/seed.js @@ -0,0 +1,20 @@ +var massive = require('massive') +var connectionString = "postgres://localhost/video_store" + +var db = massive.connectSync({connectionString : connectionString}) + +var customers = require("../db/seeds/customers.json") +var movies = require("../db/seeds/movies.json") + +for (var customer of customers) { + console.log(customer) + db.customers.saveSync(customer) +} + +for (var movie of movies) { + console.log(movie) + db.movies.saveSync(movie) +} + +console.log("seeding done!") +process.exit() From 769fbe894c6655914ae98da2e76c52e8185ef374 Mon Sep 17 00:00:00 2001 From: Adriana Date: Wed, 15 Jun 2016 17:00:05 -0700 Subject: [PATCH 12/93] Trying to get data to customers page --- controllers/customers.js | 26 ++++++++++++++++++++++++++ routes/customers.js | 6 ++++-- 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 controllers/customers.js diff --git a/controllers/customers.js b/controllers/customers.js new file mode 100644 index 000000000..7c1a92555 --- /dev/null +++ b/controllers/customers.js @@ -0,0 +1,26 @@ +var Customers = require('../lib/customers') + +CustomersController = { + locals: { + title: 'CUSTOMERS CUSTOMERS CUSTOMERS' + }, + + getCustomers: function(req, res) { + var people = new Customers + var locals = CustomersController.locals + + var db = req.app.get('db') + db.customers.find(1) + } +} + +modules.exports = CustomersController + + +// chart: function(req, res) { +// var chart = new Scorer().scoreChart() +// var locals = ScrabbleController.locals +// +// locals.chart = chart +// res.render('chart', locals) +// }, diff --git a/routes/customers.js b/routes/customers.js index 62346dbb2..26ac319d9 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -1,8 +1,10 @@ var express = require('express') var router = express.Router() +var Controller = require('../controllers/customers') + router.get('/', function(req, res) { - res.json({customers: 'customers yaaaay'}) + res.json({customers: ''}) }) -module.exports = router \ No newline at end of file +module.exports = router From 01145b5fde627dbb79113872c4a889b5d98e788e Mon Sep 17 00:00:00 2001 From: Adriana Date: Thu, 16 Jun 2016 13:46:35 -0700 Subject: [PATCH 13/93] Added in controllers and customers to get json data as the output --- controllers/customers.js | 12 +++++++++--- routes/customers.js | 4 +--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index 7c1a92555..5311f7dbd 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -6,15 +6,21 @@ CustomersController = { }, getCustomers: function(req, res) { - var people = new Customers + // var people = new Customers var locals = CustomersController.locals var db = req.app.get('db') - db.customers.find(1) + // locals.customers = db.customers.find(1) + + db.customers.find(1, function(err,results){ + //user with ID 1 + res.json(results); + }); + } } -modules.exports = CustomersController +module.exports = CustomersController // chart: function(req, res) { diff --git a/routes/customers.js b/routes/customers.js index 26ac319d9..058217aa8 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -3,8 +3,6 @@ var router = express.Router() var Controller = require('../controllers/customers') -router.get('/', function(req, res) { - res.json({customers: ''}) -}) +router.get('/', Controller.getCustomers) module.exports = router From 8d3924c9bda79fefcd30dced6ad9085579c154e3 Mon Sep 17 00:00:00 2001 From: Jessica Date: Thu, 16 Jun 2016 13:51:19 -0700 Subject: [PATCH 14/93] getting all customers working --- controllers/customers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controllers/customers.js b/controllers/customers.js index 5311f7dbd..b272b57f4 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -12,7 +12,7 @@ CustomersController = { var db = req.app.get('db') // locals.customers = db.customers.find(1) - db.customers.find(1, function(err,results){ + db.customers.find(function(err,results){ //user with ID 1 res.json(results); }); From d44c8ac89098b4375302a17b68e0a93b41c39433 Mon Sep 17 00:00:00 2001 From: Jessica Date: Thu, 16 Jun 2016 14:51:56 -0700 Subject: [PATCH 15/93] moved customer.all function to model and rendered json data from controller. --- app.js | 2 ++ controllers/customers.js | 26 +++++++++++++++++--------- db/setup/schema.sql | 2 +- models/customer.js | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 models/customer.js diff --git a/app.js b/app.js index fdc3590ac..cf354cb80 100644 --- a/app.js +++ b/app.js @@ -8,6 +8,8 @@ var routes = require('./routes/index') var app = express() var massive = require("massive") + +var app = module.exports = express() var connectionString = "postgres://localhost/video_store" // connect to Massive and get the db instance. You can safely use the diff --git a/controllers/customers.js b/controllers/customers.js index b272b57f4..2e075fca6 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -1,4 +1,4 @@ -var Customers = require('../lib/customers') +var Customer = require('../models/customer') CustomersController = { locals: { @@ -6,17 +6,25 @@ CustomersController = { }, getCustomers: function(req, res) { + Customer.all (function (error, customers) { + if (error) { + var err = new Error("Error retrieving customer list:\n" + error.message); + err.status = 500; + next(err); + } else { + res.json(customers) + } + }) // var people = new Customers - var locals = CustomersController.locals + // var locals = CustomersController.locals - var db = req.app.get('db') - // locals.customers = db.customers.find(1) - - db.customers.find(function(err,results){ - //user with ID 1 - res.json(results); - }); + // var db = req.app.get('db') + // // locals.customers = db.customers.find(1) + // db.customers.find(function(err,results){ + // //user with ID 1 + // res.json(results); + // }); } } diff --git a/db/setup/schema.sql b/db/setup/schema.sql index 558769f40..70f13e7f1 100644 --- a/db/setup/schema.sql +++ b/db/setup/schema.sql @@ -8,7 +8,7 @@ CREATE TABLE customers( state text, postal_code text, phone text, - account_credit numeric + account_credit numeric(6, 2) ); DROP TABLE IF EXISTS movies; diff --git a/models/customer.js b/models/customer.js new file mode 100644 index 000000000..c00a80015 --- /dev/null +++ b/models/customer.js @@ -0,0 +1,32 @@ +var app = require('../app') +var db = app.get('db') + +var Customer = function (customer) { + this.id = customer.id + this.name = customer.name + this.registered_at = customer.registered_at + this.address = customer.address + this.city = customer.city + this.state = customer.state + this.postal_code = customer.postal_code + this.phone = customer.phone + this.account_credit = customer.account_credit +} + +Customer.all = function (callback) { + db.customers.find (function (error, customers) { + if (error || !customers) { + callback(error || new Error("Could not retrieve customers"), undefined); + } else { + callback(null, customers.map (function (customer) { + return new Customer(customer); + })) + } + }) +} + +// Customer.prototype.sortBy = function (name, registered_at, postal_code) { + +// } + +module.exports = Customer \ No newline at end of file From 5821a8d3a1e541109efa9398b7baa77f1d2e06d7 Mon Sep 17 00:00:00 2001 From: Jessica Date: Thu, 16 Jun 2016 15:02:47 -0700 Subject: [PATCH 16/93] added first fucking test for customers controller and it is PASSING --- models/customer.js | 2 +- spec/controllers/customers.spec.js | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 spec/controllers/customers.spec.js diff --git a/models/customer.js b/models/customer.js index c00a80015..22f3ba5e5 100644 --- a/models/customer.js +++ b/models/customer.js @@ -19,7 +19,7 @@ Customer.all = function (callback) { callback(error || new Error("Could not retrieve customers"), undefined); } else { callback(null, customers.map (function (customer) { - return new Customer(customer); + return new Customer(customer) })) } }) diff --git a/spec/controllers/customers.spec.js b/spec/controllers/customers.spec.js new file mode 100644 index 000000000..2946e64b1 --- /dev/null +++ b/spec/controllers/customers.spec.js @@ -0,0 +1,19 @@ +var request = require("request") + +var baseUrl = "http://localhost:3000" + + +describe("CustomersController", function() { + var url = function(endpoint) { + return baseUrl + "/customers" + endpoint + } + + describe("#getCustomers", function() { + it("returns a Success response", function(done) { + request.get(url("/"), function(error, response, body) { + expect(response.statusCode).toBe(200) + done() + }) + }) + }) +}) \ No newline at end of file From e238cae35f13d154f2af8cb279f8cff53688bb93 Mon Sep 17 00:00:00 2001 From: Jessica Date: Thu, 16 Jun 2016 15:26:35 -0700 Subject: [PATCH 17/93] added two more passing tests weeee --- spec/controllers/customers.spec.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/spec/controllers/customers.spec.js b/spec/controllers/customers.spec.js index 2946e64b1..92707187a 100644 --- a/spec/controllers/customers.spec.js +++ b/spec/controllers/customers.spec.js @@ -8,12 +8,31 @@ describe("CustomersController", function() { return baseUrl + "/customers" + endpoint } - describe("#getCustomers", function() { + describe("#getCustomers", function(done) { it("returns a Success response", function(done) { request.get(url("/"), function(error, response, body) { expect(response.statusCode).toBe(200) done() }) }) + + it("returns JSON", function(done) { + request.get(url("/"), function(error, response, body) { + expect(response.headers['content-type']).toContain('application/json') + done() + }) + }) + + it("should be an array of objects", function(done) { + request.get(url("/"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') + + for (var record of data) { + expect(Object.keys(record)).toEqual([ 'id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit' ]) + } + done() + }) + }) }) }) \ No newline at end of file From b194f8b6ecc7f7889e8101306bf01424f6b3f64d Mon Sep 17 00:00:00 2001 From: Adriana Date: Thu, 16 Jun 2016 15:58:28 -0700 Subject: [PATCH 18/93] Added a show page for just one customer --- controllers/customers.js | 37 ++++++++++++++++++++----------------- models/customer.js | 13 ++++++++++--- routes/customers.js | 4 ++++ 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index 2e075fca6..e88ca0424 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -15,26 +15,29 @@ CustomersController = { res.json(customers) } }) - // var people = new Customers - // var locals = CustomersController.locals + }, + + getCustomersShow: function(req, res) { + Customer.find(req.params.id, function(error, customer) { - // var db = req.app.get('db') - // // locals.customers = db.customers.find(1) + if(error) { + var err = new Error("No such customer"); + err.status = 404; + next(err); + } else { + res.json(customer) - // db.customers.find(function(err,results){ - // //user with ID 1 - // res.json(results); - // }); + // customer.getBalance(function(error, balance) { + // res.render("customers/show", { + // customer: { + // id: customer.id, + // balance: balance + // } + // }); + // }); + } + }) } } module.exports = CustomersController - - -// chart: function(req, res) { -// var chart = new Scorer().scoreChart() -// var locals = ScrabbleController.locals -// -// locals.chart = chart -// res.render('chart', locals) -// }, diff --git a/models/customer.js b/models/customer.js index 22f3ba5e5..eaad4848a 100644 --- a/models/customer.js +++ b/models/customer.js @@ -25,8 +25,15 @@ Customer.all = function (callback) { }) } -// Customer.prototype.sortBy = function (name, registered_at, postal_code) { +Customer.find = function(id, callback) { + db.customers.findOne({id: id}, function(error, customer) { + if(error || !customer) { + callback(error || new Error("Customer not found"), undefined); + } else { + callback(null, new Customer(customer)); + } + }); +}; -// } -module.exports = Customer \ No newline at end of file +module.exports = Customer diff --git a/routes/customers.js b/routes/customers.js index 058217aa8..b43555ea4 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -4,5 +4,9 @@ var router = express.Router() var Controller = require('../controllers/customers') router.get('/', Controller.getCustomers) +router.get('/:id', function(request, response) { + var id = request.params.id + Controller.getCustomersShow(request, response, id) +}) module.exports = router From a53ef694b490962c12d405e9cc15ab18a9537b2a Mon Sep 17 00:00:00 2001 From: Adriana Date: Thu, 16 Jun 2016 16:41:41 -0700 Subject: [PATCH 19/93] Added in a sort by function that can sort by different fields, and adds numbers and page offset --- controllers/customers.js | 13 ++++++++++++ db/sort_customers.sql | 1 + models/customer.js | 46 ++++++++++++++++++++++++++++++++++++++++ routes/customers.js | 7 +++--- 4 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 db/sort_customers.sql diff --git a/controllers/customers.js b/controllers/customers.js index e88ca0424..1ed916f6b 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -37,6 +37,19 @@ CustomersController = { // }); } }) + }, + + getCustomersSort: function(req, res) { + Customer.sort(req.params.field, req.query.n, req.query.p, function(error, customer) { + console.log(req.params); + if (error) { + var err = new Error("Error retrieving customer list:\n" + error.message); + err.status = 500; + next(err); + } else { + res.json(customer) + } + }) } } diff --git a/db/sort_customers.sql b/db/sort_customers.sql new file mode 100644 index 000000000..de6ca67dd --- /dev/null +++ b/db/sort_customers.sql @@ -0,0 +1 @@ +SELECT * FROM customers ORDER BY $1 LIMIT $2 OFFSET $3; diff --git a/models/customer.js b/models/customer.js index eaad4848a..74be9d37d 100644 --- a/models/customer.js +++ b/models/customer.js @@ -35,5 +35,51 @@ Customer.find = function(id, callback) { }); }; +Customer.sort = function(field, n, p, callback){ + db.customers.find({}, { + order: field, + limit: n, + offset: p + }, function(error, customers) { + if (error || !customers) { + callback(error || new Error("Could not retrieve customers"), undefined); + } else { + callback(null, customers.map (function (customer) { + return new Customer(customer) + })) + } + }) + + // db.sort_customers([field, n, p], function(error, customers) { + // if (error || !customers) { + // callback(error || new Error("Could not retrieve customers"), undefined); + // } else { + // callback(null, customers.map (function (customer) { + // return new Customer(customer) + // })) + // } + // }) +} + module.exports = Customer + + + + + + + + + + + + + + + + + + + +// diff --git a/routes/customers.js b/routes/customers.js index b43555ea4..7becaf1ab 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -4,9 +4,8 @@ var router = express.Router() var Controller = require('../controllers/customers') router.get('/', Controller.getCustomers) -router.get('/:id', function(request, response) { - var id = request.params.id - Controller.getCustomersShow(request, response, id) -}) +router.get('/:id', Controller.getCustomersShow) +router.get('/sort/:field', Controller.getCustomersSort) + module.exports = router From aa217410d545a14a12c97b35f2b9d37c2e69ddda Mon Sep 17 00:00:00 2001 From: Adriana Date: Thu, 16 Jun 2016 16:55:19 -0700 Subject: [PATCH 20/93] cleaned up code --- controllers/customers.js | 2 -- db/sort_customers.sql | 1 - models/customer.js | 10 ---------- 3 files changed, 13 deletions(-) delete mode 100644 db/sort_customers.sql diff --git a/controllers/customers.js b/controllers/customers.js index 1ed916f6b..92b957a52 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -19,7 +19,6 @@ CustomersController = { getCustomersShow: function(req, res) { Customer.find(req.params.id, function(error, customer) { - if(error) { var err = new Error("No such customer"); err.status = 404; @@ -41,7 +40,6 @@ CustomersController = { getCustomersSort: function(req, res) { Customer.sort(req.params.field, req.query.n, req.query.p, function(error, customer) { - console.log(req.params); if (error) { var err = new Error("Error retrieving customer list:\n" + error.message); err.status = 500; diff --git a/db/sort_customers.sql b/db/sort_customers.sql deleted file mode 100644 index de6ca67dd..000000000 --- a/db/sort_customers.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT * FROM customers ORDER BY $1 LIMIT $2 OFFSET $3; diff --git a/models/customer.js b/models/customer.js index 74be9d37d..adbbe9280 100644 --- a/models/customer.js +++ b/models/customer.js @@ -49,16 +49,6 @@ Customer.sort = function(field, n, p, callback){ })) } }) - - // db.sort_customers([field, n, p], function(error, customers) { - // if (error || !customers) { - // callback(error || new Error("Could not retrieve customers"), undefined); - // } else { - // callback(null, customers.map (function (customer) { - // return new Customer(customer) - // })) - // } - // }) } From a8d7a0a013869595ef145106de23f80ff0a9e009 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 17 Jun 2016 10:01:56 -0700 Subject: [PATCH 21/93] get /movies working to retrieve all movies. routes created for /:id and /:field --- controllers/movies.js | 55 +++++++++++++++++++++++++++++++++++++++++++ models/customer.js | 21 ----------------- models/movie.js | 24 +++++++++++++++++++ routes/movies.js | 7 +++--- 4 files changed, 83 insertions(+), 24 deletions(-) create mode 100644 controllers/movies.js create mode 100644 models/movie.js diff --git a/controllers/movies.js b/controllers/movies.js new file mode 100644 index 000000000..7b017f0d1 --- /dev/null +++ b/controllers/movies.js @@ -0,0 +1,55 @@ +var Movie = require('../models/movie') + +MoviesController = { + locals: { + title: 'MOVIES MOVIES MOVIES' + }, + + getMovies: function(req, res) { + Movie.all (function (error, movies) { + if (error) { + var err = new Error("Error retrieving movie list:\n" + error.message); + err.status = 500; + next(err); + } else { + res.json(movies) + } + }) + }, + + getMoviesShow: function(req, res) { + Movie.find(req.params.id, function(error, movie) { + if(error) { + var err = new Error("No such movies"); + err.status = 404; + next(err); + } else { + res.json(movie) + + // movie.getBalance(function(error, balance) { + // res.render("movies/show", { + // movie: { + // id: movie.id, + // balance: balance + // } + // }); + // }); + } + }) + }, + + getMoviesSort: function(req, res) { + Movie.sort(req.params.field, req.query.n, req.query.p, function(error, movie) { + if (error) { + var err = new Error("Error retrieving movie list:\n" + error.message); + err.status = 500; + next(err); + } else { + res.json(movie) + } + }) + } +} + +module.exports = MoviesController + diff --git a/models/customer.js b/models/customer.js index adbbe9280..bb9496387 100644 --- a/models/customer.js +++ b/models/customer.js @@ -51,25 +51,4 @@ Customer.sort = function(field, n, p, callback){ }) } - module.exports = Customer - - - - - - - - - - - - - - - - - - - -// diff --git a/models/movie.js b/models/movie.js new file mode 100644 index 000000000..faf71fc0e --- /dev/null +++ b/models/movie.js @@ -0,0 +1,24 @@ +var app = require('../app') +var db = app.get('db') + +var Movie = function (movie) { + this.id = movie.id + this.title = movie.title + this.overview = movie.overview + this.release_date = movie.release_date + this.inventory = movie.inventory +} + +Movie.all = function (callback) { + db.movies.find (function (error, movies) { + if (error || !movies) { + callback(error || new Error("Could not retrieve movies"), undefined); + } else { + callback(null, movies.map (function (movie) { + return new Movie(movie) + })) + } + }) +} + +module.exports = Movie \ No newline at end of file diff --git a/routes/movies.js b/routes/movies.js index fedd37fb7..f95ab6eb4 100644 --- a/routes/movies.js +++ b/routes/movies.js @@ -1,9 +1,10 @@ var express = require('express') var router = express.Router() +var Controller = require('../controllers/movies') /* GET home page. */ -router.get('/', function(req, res, next) { - res.status(200).json({movies: 'movies!!!'}) -}) +router.get('/', Controller.getMovies) +router.get('/:id', Controller.getMoviesShow) +router.get('/sort/:field', Controller.getMoviesSort) module.exports = router From 84501a76a24ce94dd35d7dd3f4cac6057c5255f6 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 17 Jun 2016 10:06:45 -0700 Subject: [PATCH 22/93] model and controller methods for find and sort working for movies. --- models/customer.js | 12 ++++++------ models/movie.js | 28 +++++++++++++++++++++++++++- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/models/customer.js b/models/customer.js index bb9496387..6901ff332 100644 --- a/models/customer.js +++ b/models/customer.js @@ -16,7 +16,7 @@ var Customer = function (customer) { Customer.all = function (callback) { db.customers.find (function (error, customers) { if (error || !customers) { - callback(error || new Error("Could not retrieve customers"), undefined); + callback(error || new Error("Could not retrieve customers"), undefined) } else { callback(null, customers.map (function (customer) { return new Customer(customer) @@ -28,12 +28,12 @@ Customer.all = function (callback) { Customer.find = function(id, callback) { db.customers.findOne({id: id}, function(error, customer) { if(error || !customer) { - callback(error || new Error("Customer not found"), undefined); + callback(error || new Error("Customer not found"), undefined) } else { - callback(null, new Customer(customer)); + callback(null, new Customer(customer)) } - }); -}; + }) +} Customer.sort = function(field, n, p, callback){ db.customers.find({}, { @@ -42,7 +42,7 @@ Customer.sort = function(field, n, p, callback){ offset: p }, function(error, customers) { if (error || !customers) { - callback(error || new Error("Could not retrieve customers"), undefined); + callback(error || new Error("Could not retrieve customers"), undefined) } else { callback(null, customers.map (function (customer) { return new Customer(customer) diff --git a/models/movie.js b/models/movie.js index faf71fc0e..546f732f3 100644 --- a/models/movie.js +++ b/models/movie.js @@ -12,7 +12,33 @@ var Movie = function (movie) { Movie.all = function (callback) { db.movies.find (function (error, movies) { if (error || !movies) { - callback(error || new Error("Could not retrieve movies"), undefined); + callback(error || new Error("Could not retrieve movies"), undefined) + } else { + callback(null, movies.map (function (movie) { + return new Movie(movie) + })) + } + }) +} + +Movie.find = function(id, callback) { + db.movies.findOne({id: id}, function(error, movie) { + if(error || !movie) { + callback(error || new Error("movie not found"), undefined) + } else { + callback(null, new Movie(movie)) + } + }) +} + +Movie.sort = function(field, n, p, callback){ + db.movies.find({}, { + order: field, + limit: n, + offset: p + }, function(error, movies) { + if (error || !movies) { + callback(error || new Error("Could not retrieve movies"), undefined) } else { callback(null, movies.map (function (movie) { return new Movie(movie) From 05f7e0a0ac9291c63970c87cc6ef024b36fd2221 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 17 Jun 2016 10:19:58 -0700 Subject: [PATCH 23/93] three tests for movies done and passing --- controllers/customers.js | 4 ++-- controllers/movies.js | 4 ++-- models/customer.js | 4 ++-- models/movie.js | 4 ++-- routes/customers.js | 2 +- routes/movies.js | 2 +- spec/controllers/movies.spec.js | 42 +++++++++++++++++++++++++++++---- 7 files changed, 48 insertions(+), 14 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index 92b957a52..dcb2a8f61 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -17,8 +17,8 @@ CustomersController = { }) }, - getCustomersShow: function(req, res) { - Customer.find(req.params.id, function(error, customer) { + getCustomersShow: function(req, res, next) { + Customer.find(req.params.name, function(error, customer) { if(error) { var err = new Error("No such customer"); err.status = 404; diff --git a/controllers/movies.js b/controllers/movies.js index 7b017f0d1..b04ada86f 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -17,8 +17,8 @@ MoviesController = { }) }, - getMoviesShow: function(req, res) { - Movie.find(req.params.id, function(error, movie) { + getMoviesShow: function(req, res, next) { + Movie.find(req.params.title, function(error, movie) { if(error) { var err = new Error("No such movies"); err.status = 404; diff --git a/models/customer.js b/models/customer.js index 6901ff332..0e4de9924 100644 --- a/models/customer.js +++ b/models/customer.js @@ -25,8 +25,8 @@ Customer.all = function (callback) { }) } -Customer.find = function(id, callback) { - db.customers.findOne({id: id}, function(error, customer) { +Customer.find = function(name, callback) { + db.customers.findOne({name: name}, function(error, customer) { if(error || !customer) { callback(error || new Error("Customer not found"), undefined) } else { diff --git a/models/movie.js b/models/movie.js index 546f732f3..e41df3c5d 100644 --- a/models/movie.js +++ b/models/movie.js @@ -21,8 +21,8 @@ Movie.all = function (callback) { }) } -Movie.find = function(id, callback) { - db.movies.findOne({id: id}, function(error, movie) { +Movie.find = function(title, callback) { + db.movies.findOne({title: title}, function(error, movie) { if(error || !movie) { callback(error || new Error("movie not found"), undefined) } else { diff --git a/routes/customers.js b/routes/customers.js index 7becaf1ab..77f5734e9 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -4,7 +4,7 @@ var router = express.Router() var Controller = require('../controllers/customers') router.get('/', Controller.getCustomers) -router.get('/:id', Controller.getCustomersShow) +router.get('/:name', Controller.getCustomersShow) router.get('/sort/:field', Controller.getCustomersSort) diff --git a/routes/movies.js b/routes/movies.js index f95ab6eb4..58f98d9c2 100644 --- a/routes/movies.js +++ b/routes/movies.js @@ -4,7 +4,7 @@ var Controller = require('../controllers/movies') /* GET home page. */ router.get('/', Controller.getMovies) -router.get('/:id', Controller.getMoviesShow) +router.get('/:title', Controller.getMoviesShow) router.get('/sort/:field', Controller.getMoviesSort) module.exports = router diff --git a/spec/controllers/movies.spec.js b/spec/controllers/movies.spec.js index ddcaf2f68..3599420fa 100644 --- a/spec/controllers/movies.spec.js +++ b/spec/controllers/movies.spec.js @@ -1,5 +1,39 @@ -var request = require('request'); +var request = require("request") -describe("Endpoints under /movies", function() { - -}) +var baseUrl = "http://localhost:3000" + + +describe("MoviesController", function() { + var url = function(endpoint) { + return baseUrl + "/movies" + endpoint + } + + describe("#getMovies", function(done) { + it("returns a Success response", function(done) { + request.get(url("/"), function(error, response, body) { + expect(response.statusCode).toBe(200) + done() + }) + }) + + + it("returns JSON", function(done) { + request.get(url("/"), function(error, response, body) { + expect(response.headers['content-type']).toContain('application/json') + done() + }) + }) + + it("should be an array of objects", function(done) { + request.get(url("/"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') + + for (var record of data) { + expect(Object.keys(record)).toEqual([ 'id', 'title', 'overview', 'release_date', 'inventory']) + } + done() + }) + }) + }) +}) \ No newline at end of file From dcd0b51f083579e47192b6bf0eb6fe2d7bd87349 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 17 Jun 2016 11:00:52 -0700 Subject: [PATCH 24/93] test for finding a movie based on title written and passing --- spec/models/customer.spec.js | 0 spec/models/movie.spec.js | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 spec/models/customer.spec.js create mode 100644 spec/models/movie.spec.js diff --git a/spec/models/customer.spec.js b/spec/models/customer.spec.js new file mode 100644 index 000000000..e69de29bb diff --git a/spec/models/movie.spec.js b/spec/models/movie.spec.js new file mode 100644 index 000000000..3c5a979c0 --- /dev/null +++ b/spec/models/movie.spec.js @@ -0,0 +1,24 @@ +var app = require('../../app') +var db = app.get('db') + +var Movie = require('../../models/movie') + +describe('Movie', function () { +// // var movie1 = new Movie +// var title1 = "Jaws" +// var title2 = "Alien" + + afterEach(function () { + db.end() + }) + + describe('#find', function () { + it('should return correct movie', function (done) { + Movie.find("Jaws", function (error, movie1) { + expect(movie1.title).toEqual("Jaws") + expect(error).toBeNull + done() + }) + }) + }) +}) From db043303cabc68870937aeed6af5f7855473769f Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 17 Jun 2016 11:04:43 -0700 Subject: [PATCH 25/93] minor movies test revision to use var for title and remove magic string --- spec/models/movie.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/models/movie.spec.js b/spec/models/movie.spec.js index 3c5a979c0..4b4e1a11c 100644 --- a/spec/models/movie.spec.js +++ b/spec/models/movie.spec.js @@ -5,7 +5,7 @@ var Movie = require('../../models/movie') describe('Movie', function () { // // var movie1 = new Movie -// var title1 = "Jaws" + var title1 = "Alien" // var title2 = "Alien" afterEach(function () { @@ -14,8 +14,8 @@ describe('Movie', function () { describe('#find', function () { it('should return correct movie', function (done) { - Movie.find("Jaws", function (error, movie1) { - expect(movie1.title).toEqual("Jaws") + Movie.find(title1, function (error, movie1) { + expect(movie1.title).toEqual(title1) expect(error).toBeNull done() }) From 1a848f6ad64e653753bd078f7089b5099b11bd83 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 17 Jun 2016 13:20:52 -0700 Subject: [PATCH 26/93] Added in more tests for customers. Added a negative test for giving wrong info in --- models/customer.js | 2 +- spec/models/customer.spec.js | 86 ++++++++++++++++++++++++++++++++++++ spec/models/movie.spec.js | 30 ++++++++++++- 3 files changed, 115 insertions(+), 3 deletions(-) diff --git a/models/customer.js b/models/customer.js index 0e4de9924..37d2c21ed 100644 --- a/models/customer.js +++ b/models/customer.js @@ -42,7 +42,7 @@ Customer.sort = function(field, n, p, callback){ offset: p }, function(error, customers) { if (error || !customers) { - callback(error || new Error("Could not retrieve customers"), undefined) + callback(new Error("Could not retrieve customers"), undefined) } else { callback(null, customers.map (function (customer) { return new Customer(customer) diff --git a/spec/models/customer.spec.js b/spec/models/customer.spec.js index e69de29bb..ca4747143 100644 --- a/spec/models/customer.spec.js +++ b/spec/models/customer.spec.js @@ -0,0 +1,86 @@ +var app = require('../../app') +var db = app.get('db') + +var Customer = require('../../models/customer') + +describe('Customer', function () { + var customer1 = "Acton Gilliam" + var registered_at1 = "Thu, 26 Feb 2015 20:00:53 -0800" + var address1 = 'Ap #508-8214 Senectus Av.' + var city1 = "Portland" + var state1 = "Oregon" + var postal_code1 = "62594" + var phone1 = "(903) 973-1984" + var account_credit1 = "48.64" + + afterEach(function () { + db.end() + }) + + describe('#all', function () { + it('should return all customers', function (done) { + Customer.all(function (error, customers) { + expect(customers.length).toEqual(200) + }) + done() + }) + }) + + describe('#find', function () { + it('should return correct customer', function (done) { + Customer.find(customer1, function (error, customer) { + expect(customer.name).toEqual(customer1) + expect(customer.registered_at).toEqual(registered_at1) + expect(customer.address).toEqual(address1) + expect(customer.city).toEqual(city1) + expect(customer.state).toEqual(state1) + expect(customer.postal_code).toEqual(postal_code1) + expect(customer.phone).toEqual(phone1) + expect(customer.account_credit).toEqual(account_credit1) + expect(error).toBeNull + done() + }) + }) + }) + + describe('#sort', function () { + it('should sort customer by name', function(done) { + Customer.sort("name", 1, 3, function(error, customer_array) { + expect(customer_array.length).toEqual(1) + expect(customer_array[0].name).toEqual(customer1) + expect(customer_array[0].registered_at).toEqual(registered_at1) + expect(customer_array[0].address).toEqual(address1) + expect(customer_array[0].city).toEqual(city1) + expect(customer_array[0].state).toEqual(state1) + expect(customer_array[0].postal_code).toEqual(postal_code1) + expect(customer_array[0].phone).toEqual(phone1) + expect(customer_array[0].account_credit).toEqual(account_credit1) + expect(error).toBeNull + }) + done() + }) + + it('should throw an error if the customer DNE', function (done) { + Customer.sort("abcd", 1, 3, function(error, customer_array2) { + expect(error.message).toEqual("Could not retrieve customers") + }) + done() + }) + }) +}) + + + + + + + + + + + + + + + +// diff --git a/spec/models/movie.spec.js b/spec/models/movie.spec.js index 4b4e1a11c..a7fd5daeb 100644 --- a/spec/models/movie.spec.js +++ b/spec/models/movie.spec.js @@ -4,21 +4,47 @@ var db = app.get('db') var Movie = require('../../models/movie') describe('Movie', function () { -// // var movie1 = new Movie var title1 = "Alien" -// var title2 = "Alien" + var overview1 = 'During its return to the earth, commercial spaceship Nostromo intercepts a distress signal from a distant planet. When a three-member team of the crew discovers a chamber containing thousands of eggs on the planet, a creature inside one of the eggs attacks an explorer. The entire crew is unaware of the impending nightmare set to descend upon them when the alien parasite planted inside its unfortunate host is birthed.' + var release_date1 = '1979-05-25' + var inventory1 = 4 afterEach(function () { db.end() }) + describe('#all', function () { + it('should return all movies', function (done) { + Movie.all(function (error, movies) { + expect(movies.length).toEqual(100) + }) + done() + }) + }) + describe('#find', function () { it('should return correct movie', function (done) { Movie.find(title1, function (error, movie1) { expect(movie1.title).toEqual(title1) + expect(movie1.overview).toEqual(overview1) + expect(movie1.release_date).toEqual(release_date1) + expect(movie1.inventory).toEqual(inventory1) expect(error).toBeNull done() }) }) }) + + describe('#sort', function () { + it('should sort movie by title', function(done) { + Movie.sort("title", 1, 3, function(error, movie_array) { + expect(movie_array.length).toEqual(1) + expect(movie_array[0].title).toEqual(title1) + expect(movie_array[0].overview).toEqual(overview1) + expect(movie_array[0].release_date).toEqual(release_date1) + expect(movie_array[0].inventory).toEqual(inventory1) + }) + done() + }) + }) }) From 2205615b7279dfed7c480c3be2627cdabec0557e Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 17 Jun 2016 13:28:36 -0700 Subject: [PATCH 27/93] Added in negative tests for movies and for customers --- models/customer.js | 2 +- spec/models/customer.spec.js | 7 +++++++ spec/models/movie.spec.js | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/models/customer.js b/models/customer.js index 37d2c21ed..92a94888d 100644 --- a/models/customer.js +++ b/models/customer.js @@ -28,7 +28,7 @@ Customer.all = function (callback) { Customer.find = function(name, callback) { db.customers.findOne({name: name}, function(error, customer) { if(error || !customer) { - callback(error || new Error("Customer not found"), undefined) + callback(new Error("Customer not found"), undefined) } else { callback(null, new Customer(customer)) } diff --git a/spec/models/customer.spec.js b/spec/models/customer.spec.js index ca4747143..e5309c4a9 100644 --- a/spec/models/customer.spec.js +++ b/spec/models/customer.spec.js @@ -41,6 +41,13 @@ describe('Customer', function () { done() }) }) + + it('should throw an error if the customer DNE', function (done) { + Customer.find("person", function(error, customer) { + expect(error.message).toEqual("Customer not found") + }) + done() + }) }) describe('#sort', function () { diff --git a/spec/models/movie.spec.js b/spec/models/movie.spec.js index a7fd5daeb..59a68d241 100644 --- a/spec/models/movie.spec.js +++ b/spec/models/movie.spec.js @@ -33,6 +33,13 @@ describe('Movie', function () { done() }) }) + + it('should throw an error if the movie DNE', function (done) { + Movie.find("bad title", function(error, customer) { + expect(error.message).toEqual("movie not found") + }) + done() + }) }) describe('#sort', function () { @@ -46,5 +53,12 @@ describe('Movie', function () { }) done() }) + + it('should throw an error if the customer DNE', function (done) { + Movie.sort("bad title", 1, 3, function(error, movie) { + expect(error.message).toEqual("Customer not retrieve movies") + }) + done() + }) }) }) From e7f12f1e9949e79dc7440b5a2a0f14d849cd4874 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 17 Jun 2016 13:29:58 -0700 Subject: [PATCH 28/93] Took out lower level error --- models/movie.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/models/movie.js b/models/movie.js index e41df3c5d..15a7b94e5 100644 --- a/models/movie.js +++ b/models/movie.js @@ -12,7 +12,7 @@ var Movie = function (movie) { Movie.all = function (callback) { db.movies.find (function (error, movies) { if (error || !movies) { - callback(error || new Error("Could not retrieve movies"), undefined) + callback(new Error("Could not retrieve movies"), undefined) } else { callback(null, movies.map (function (movie) { return new Movie(movie) @@ -24,7 +24,7 @@ Movie.all = function (callback) { Movie.find = function(title, callback) { db.movies.findOne({title: title}, function(error, movie) { if(error || !movie) { - callback(error || new Error("movie not found"), undefined) + callback(new Error("movie not found"), undefined) } else { callback(null, new Movie(movie)) } @@ -47,4 +47,4 @@ Movie.sort = function(field, n, p, callback){ }) } -module.exports = Movie \ No newline at end of file +module.exports = Movie From 78b0ef54520f5f4821802c89afe327d855ea0295 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 17 Jun 2016 13:33:27 -0700 Subject: [PATCH 29/93] added movie_id to schema --- db/setup/schema.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/setup/schema.sql b/db/setup/schema.sql index 70f13e7f1..b58e9041c 100644 --- a/db/setup/schema.sql +++ b/db/setup/schema.sql @@ -24,6 +24,7 @@ DROP TABLE IF EXISTS rentals; CREATE TABLE rentals( id serial PRIMARY KEY, customer_id int, + movie_id int, check_in boolean, check_out boolean, return_date text From 529da058bec2f77527a41493b52a52bbb3cb9691 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 17 Jun 2016 15:10:44 -0700 Subject: [PATCH 30/93] find all movies that can be rented works. find rentals by title now working --- controllers/rentals.js | 33 +++++++++++++++++++++++++++++++++ models/rental.js | 32 ++++++++++++++++++++++++++++++++ routes/index.js | 1 - routes/movies.js | 1 - routes/rentals.js | 13 +++++++------ 5 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 controllers/rentals.js create mode 100644 models/rental.js diff --git a/controllers/rentals.js b/controllers/rentals.js new file mode 100644 index 000000000..354748951 --- /dev/null +++ b/controllers/rentals.js @@ -0,0 +1,33 @@ +var Rental = require('../models/rental') + +RentalsController = { + locals: { + title: 'RENTALS RENTALS RENTALS' + }, + + getRentals: function(req, res) { + Rental.all (function (error, movies) { + if (error) { + var err = new Error("Error retrieving rental list:\n" + error.message); + err.status = 500; + next(err); + } else { + res.json(movies) + } + }) + }, + + getRentalsShow: function(req, res, next) { + Rental.find (req.params.title, function(error, rental) { + if (error) { + var err = new Error("No such rentals"); + err.status = 404; + next(err); + } else { + res.json(rental) + } + }) + } +} + +module.exports = RentalsController diff --git a/models/rental.js b/models/rental.js new file mode 100644 index 000000000..1c0275cf8 --- /dev/null +++ b/models/rental.js @@ -0,0 +1,32 @@ +var app = require('../app') +var db = app.get('db') +var Movie = require('./movie') + +var Rental = function () {} + +Rental.all = function (callback) { + db.movies.find (function (error, movies) { + if (error || !movies) { + callback(new Error("Could not retrieve movies"), undefined) + } else { + callback(null, movies.map (function (movie) { + return new Movie(movie) + })) + } + }) +} + +Rental.find = function (title, callback) { + db.movies.search({columns:["title"], term: title}, function (error, movies) { + if (error || !movies) { + callback(new Error("Could not retrieve movies"), undefined) + } else { + callback(null, movies.map (function (movie) { + return new Movie(movie) + })) + } + }) +} + + +module.exports = Rental \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index 24bda7d04..7198e54e0 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,7 +1,6 @@ var express = require('express') var router = express.Router() -/* GET home page. */ router.get('/', function(req, res, next) { res.status(200).json({whatevs: 'whatevs!!!'}) }) diff --git a/routes/movies.js b/routes/movies.js index 58f98d9c2..ad4a06f8d 100644 --- a/routes/movies.js +++ b/routes/movies.js @@ -2,7 +2,6 @@ var express = require('express') var router = express.Router() var Controller = require('../controllers/movies') -/* GET home page. */ router.get('/', Controller.getMovies) router.get('/:title', Controller.getMoviesShow) router.get('/sort/:field', Controller.getMoviesSort) diff --git a/routes/rentals.js b/routes/rentals.js index f5a385416..a8e74ba66 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -1,12 +1,13 @@ var express = require('express') var router = express.Router() +var Controller = require('../controllers/rentals') -router.get('/', function(req, res) { - res.json({rentals: 'home for rentals!!'}) -}) +// router.get('/', function (req, res) { +// res.json({rentals: "home for rentals!"}) +// }) -router.get('/:title', function(req, res) { - res.json({rentals: 'rentals!!'}) -}) +router.get('/', Controller.getRentals) +router.get('/:title', Controller.getRentalsShow) +// router.get('/:title/customers', Controller.getRentalStatus) module.exports = router \ No newline at end of file From 47c9e4f60ea09e5017ed4a9b8a596b0cbd31b6c7 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 17 Jun 2016 15:23:01 -0700 Subject: [PATCH 31/93] changed schema --- db/setup/schema.sql | 3 +-- routes/rentals.js | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/db/setup/schema.sql b/db/setup/schema.sql index b58e9041c..508afd399 100644 --- a/db/setup/schema.sql +++ b/db/setup/schema.sql @@ -25,7 +25,6 @@ CREATE TABLE rentals( id serial PRIMARY KEY, customer_id int, movie_id int, - check_in boolean, - check_out boolean, + status boolean, return_date text ); diff --git a/routes/rentals.js b/routes/rentals.js index a8e74ba66..24c113dbc 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -2,12 +2,8 @@ var express = require('express') var router = express.Router() var Controller = require('../controllers/rentals') -// router.get('/', function (req, res) { -// res.json({rentals: "home for rentals!"}) -// }) - router.get('/', Controller.getRentals) router.get('/:title', Controller.getRentalsShow) // router.get('/:title/customers', Controller.getRentalStatus) -module.exports = router \ No newline at end of file +module.exports = router From 63a2dc805abf0c8cfac4f923511d747240b4e1a8 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 17 Jun 2016 15:36:31 -0700 Subject: [PATCH 32/93] Added in controller testing --- spec/controllers/rentals.spec.js | 38 +++++++++++++ spec/models/rental.spec.js | 93 ++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 spec/controllers/rentals.spec.js create mode 100644 spec/models/rental.spec.js diff --git a/spec/controllers/rentals.spec.js b/spec/controllers/rentals.spec.js new file mode 100644 index 000000000..0b20fbda7 --- /dev/null +++ b/spec/controllers/rentals.spec.js @@ -0,0 +1,38 @@ +var request = require("request") + +var baseUrl = "http://localhost:3000" + + +describe("RentalsController", function() { + var url = function(endpoint) { + return baseUrl + "/rentals" + endpoint + } +// + describe("#getRentals", function(done) { + it("returns a Success response", function(done) { + request.get(url("/"), function(error, response, body) { + expect(response.statusCode).toBe(200) + done() + }) + }) +// + it("returns JSON", function(done) { + request.get(url("/"), function(error, response, body) { + expect(response.headers['content-type']).toContain('application/json') + done() + }) + }) +// + it("should be an array of objects", function(done) { + request.get(url("/"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') + + for (var record of data) { + expect(Object.keys(record)).toEqual([ 'id', 'title', 'overview', 'release_date', 'inventory' ]) + } + done() + }) + }) + }) +}) diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js new file mode 100644 index 000000000..3e9201703 --- /dev/null +++ b/spec/models/rental.spec.js @@ -0,0 +1,93 @@ +var app = require('../../app') +var db = app.get('db') + +var Rental = require('../../models/customer') + +// describe('Rental', function () { +// var customer1 = "Acton Gilliam" +// var registered_at1 = "Thu, 26 Feb 2015 20:00:53 -0800" +// var address1 = 'Ap #508-8214 Senectus Av.' +// var city1 = "Portland" +// var state1 = "Oregon" +// var postal_code1 = "62594" +// var phone1 = "(903) 973-1984" +// var account_credit1 = "48.64" +// +// afterEach(function () { +// db.end() +// }) +// +// describe('#all', function () { +// it('should return all customers', function (done) { +// Rental.all(function (error, customers) { +// expect(customers.length).toEqual(200) +// }) +// done() +// }) +// }) +// +// describe('#find', function () { +// it('should return correct customer', function (done) { +// Rental.find(customer1, function (error, customer) { +// expect(customer.name).toEqual(customer1) +// expect(customer.registered_at).toEqual(registered_at1) +// expect(customer.address).toEqual(address1) +// expect(customer.city).toEqual(city1) +// expect(customer.state).toEqual(state1) +// expect(customer.postal_code).toEqual(postal_code1) +// expect(customer.phone).toEqual(phone1) +// expect(customer.account_credit).toEqual(account_credit1) +// expect(error).toBeNull +// done() +// }) +// }) +// +// it('should throw an error if the customer DNE', function (done) { +// Rental.find("person", function(error, customer) { +// expect(error.message).toEqual("Rental not found") +// }) +// done() +// }) +// }) +// +// describe('#sort', function () { +// it('should sort customer by name', function(done) { +// Rental.sort("name", 1, 3, function(error, customer_array) { +// expect(customer_array.length).toEqual(1) +// expect(customer_array[0].name).toEqual(customer1) +// expect(customer_array[0].registered_at).toEqual(registered_at1) +// expect(customer_array[0].address).toEqual(address1) +// expect(customer_array[0].city).toEqual(city1) +// expect(customer_array[0].state).toEqual(state1) +// expect(customer_array[0].postal_code).toEqual(postal_code1) +// expect(customer_array[0].phone).toEqual(phone1) +// expect(customer_array[0].account_credit).toEqual(account_credit1) +// expect(error).toBeNull +// }) +// done() +// }) +// +// it('should throw an error if the customer DNE', function (done) { +// Rental.sort("abcd", 1, 3, function(error, customer_array2) { +// expect(error.message).toEqual("Could not retrieve customers") +// }) +// done() +// }) +// }) +// }) + + + + + + + + + + + + + + + +// From 65ad737b2424540c3b2a63ff411c64bacb992892 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 17 Jun 2016 15:45:06 -0700 Subject: [PATCH 33/93] Added in controller testing for rentals for show page --- spec/controllers/rentals.spec.js | 34 +++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/spec/controllers/rentals.spec.js b/spec/controllers/rentals.spec.js index 0b20fbda7..3af4d4ca5 100644 --- a/spec/controllers/rentals.spec.js +++ b/spec/controllers/rentals.spec.js @@ -7,7 +7,7 @@ describe("RentalsController", function() { var url = function(endpoint) { return baseUrl + "/rentals" + endpoint } -// + describe("#getRentals", function(done) { it("returns a Success response", function(done) { request.get(url("/"), function(error, response, body) { @@ -15,14 +15,14 @@ describe("RentalsController", function() { done() }) }) -// + it("returns JSON", function(done) { request.get(url("/"), function(error, response, body) { expect(response.headers['content-type']).toContain('application/json') done() }) }) -// + it("should be an array of objects", function(done) { request.get(url("/"), function(error, response, body) { var data = JSON.parse(body) @@ -35,4 +35,32 @@ describe("RentalsController", function() { }) }) }) + + describe('#getRentalsShow', function(done) { + it('returns a success response', function(done) { + request.get(url("/Jaws"), function(error, response, body) { + expect(response.statusCode).toBe(200) + done() + }) + }) + + it("returns JSON", function(done) { + request.get(url("/Jaws"), function(error, response, body) { + expect(response.headers['content-type']).toContain('application/json') + done() + }) + }) + + it("should be an array of objects", function(done) { + request.get(url("/Jaws"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') + + for (var record of data) { + expect(Object.keys(record)).toEqual([ 'id', 'title', 'overview', 'release_date', 'inventory' ]) + } + done() + }) + }) + }) }) From 5bdd0d21b8d4d4b4dd7d6b50d94b6c1bc99d5f98 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 17 Jun 2016 15:54:16 -0700 Subject: [PATCH 34/93] Added customer testing for show page --- spec/controllers/customers.spec.js | 46 ++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/spec/controllers/customers.spec.js b/spec/controllers/customers.spec.js index 92707187a..ae986e07d 100644 --- a/spec/controllers/customers.spec.js +++ b/spec/controllers/customers.spec.js @@ -24,15 +24,43 @@ describe("CustomersController", function() { }) it("should be an array of objects", function(done) { - request.get(url("/"), function(error, response, body) { - var data = JSON.parse(body) - expect(typeof data).toEqual('object') - - for (var record of data) { - expect(Object.keys(record)).toEqual([ 'id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit' ]) - } - done() + request.get(url("/"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') + + for (var record of data) { + expect(Object.keys(record)).toEqual([ 'id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit' ]) + } + done() + }) }) }) + + describe('#getCustomersShow', function(done) { + it('returns a success response', function(done) { + request.get(url("/Curran Stout"), function(error, response, body) { + expect(response.statusCode).toBe(200) + done() + }) + }) + + it("returns JSON", function(done) { + request.get(url("/Curran Stout"), function(error, response, body) { + expect(response.headers['content-type']).toContain('application/json') + done() + }) + }) + + it("should be an array of objects", function(done) { + request.get(url("/Curran Stout"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') + + // for (var record of data) { + expect(Object.keys(data)).toEqual([ 'id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit' ]) + // } + done() + }) + }) }) -}) \ No newline at end of file +}) From ff1ca1ad41294d96c6118dfbe26a37177827d90e Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 17 Jun 2016 15:56:17 -0700 Subject: [PATCH 35/93] Cleaned up customers controller page --- controllers/customers.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index dcb2a8f61..b95c84d0d 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -25,15 +25,6 @@ CustomersController = { next(err); } else { res.json(customer) - - // customer.getBalance(function(error, balance) { - // res.render("customers/show", { - // customer: { - // id: customer.id, - // balance: balance - // } - // }); - // }); } }) }, From 5d34cc3d80c6f49f7bf2f6df6c8d9db04155aba9 Mon Sep 17 00:00:00 2001 From: Adriana Date: Sat, 18 Jun 2016 08:35:54 -0700 Subject: [PATCH 36/93] Added jasmine-testing so errors will show --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a8be03a44..5b382d61d 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "start": "nodemon ./bin/www", - "test": "clear; jasmine-node --verbose spec/", + "test": "clear; ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/", "db:drop": "dropdb video_store", "db:create": "createdb video_store", "db:schema": "node tasks/load_schema", From 05e2ced76921d77178aa24449396dd3f246e4212 Mon Sep 17 00:00:00 2001 From: Adriana Date: Sat, 18 Jun 2016 09:21:28 -0700 Subject: [PATCH 37/93] Added rental tests --- models/movie.js | 2 +- models/rental.js | 2 +- spec/models/movie.spec.js | 2 +- spec/models/rental.spec.js | 156 ++++++++++++++++--------------------- 4 files changed, 69 insertions(+), 93 deletions(-) diff --git a/models/movie.js b/models/movie.js index 15a7b94e5..0d31cc9ce 100644 --- a/models/movie.js +++ b/models/movie.js @@ -38,7 +38,7 @@ Movie.sort = function(field, n, p, callback){ offset: p }, function(error, movies) { if (error || !movies) { - callback(error || new Error("Could not retrieve movies"), undefined) + callback(new Error("Could not retrieve movies"), undefined) } else { callback(null, movies.map (function (movie) { return new Movie(movie) diff --git a/models/rental.js b/models/rental.js index 1c0275cf8..52cd02cb7 100644 --- a/models/rental.js +++ b/models/rental.js @@ -29,4 +29,4 @@ Rental.find = function (title, callback) { } -module.exports = Rental \ No newline at end of file +module.exports = Rental diff --git a/spec/models/movie.spec.js b/spec/models/movie.spec.js index 59a68d241..6e1733b1e 100644 --- a/spec/models/movie.spec.js +++ b/spec/models/movie.spec.js @@ -56,7 +56,7 @@ describe('Movie', function () { it('should throw an error if the customer DNE', function (done) { Movie.sort("bad title", 1, 3, function(error, movie) { - expect(error.message).toEqual("Customer not retrieve movies") + expect(error.message).toEqual("Could not retrieve movies") }) done() }) diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js index 3e9201703..7710523ca 100644 --- a/spec/models/rental.spec.js +++ b/spec/models/rental.spec.js @@ -1,93 +1,69 @@ var app = require('../../app') var db = app.get('db') -var Rental = require('../../models/customer') - -// describe('Rental', function () { -// var customer1 = "Acton Gilliam" -// var registered_at1 = "Thu, 26 Feb 2015 20:00:53 -0800" -// var address1 = 'Ap #508-8214 Senectus Av.' -// var city1 = "Portland" -// var state1 = "Oregon" -// var postal_code1 = "62594" -// var phone1 = "(903) 973-1984" -// var account_credit1 = "48.64" -// -// afterEach(function () { -// db.end() -// }) -// -// describe('#all', function () { -// it('should return all customers', function (done) { -// Rental.all(function (error, customers) { -// expect(customers.length).toEqual(200) -// }) -// done() -// }) -// }) -// -// describe('#find', function () { -// it('should return correct customer', function (done) { -// Rental.find(customer1, function (error, customer) { -// expect(customer.name).toEqual(customer1) -// expect(customer.registered_at).toEqual(registered_at1) -// expect(customer.address).toEqual(address1) -// expect(customer.city).toEqual(city1) -// expect(customer.state).toEqual(state1) -// expect(customer.postal_code).toEqual(postal_code1) -// expect(customer.phone).toEqual(phone1) -// expect(customer.account_credit).toEqual(account_credit1) -// expect(error).toBeNull -// done() -// }) -// }) -// -// it('should throw an error if the customer DNE', function (done) { -// Rental.find("person", function(error, customer) { -// expect(error.message).toEqual("Rental not found") -// }) -// done() -// }) -// }) -// -// describe('#sort', function () { -// it('should sort customer by name', function(done) { -// Rental.sort("name", 1, 3, function(error, customer_array) { -// expect(customer_array.length).toEqual(1) -// expect(customer_array[0].name).toEqual(customer1) -// expect(customer_array[0].registered_at).toEqual(registered_at1) -// expect(customer_array[0].address).toEqual(address1) -// expect(customer_array[0].city).toEqual(city1) -// expect(customer_array[0].state).toEqual(state1) -// expect(customer_array[0].postal_code).toEqual(postal_code1) -// expect(customer_array[0].phone).toEqual(phone1) -// expect(customer_array[0].account_credit).toEqual(account_credit1) -// expect(error).toBeNull -// }) -// done() -// }) -// -// it('should throw an error if the customer DNE', function (done) { -// Rental.sort("abcd", 1, 3, function(error, customer_array2) { -// expect(error.message).toEqual("Could not retrieve customers") -// }) -// done() -// }) -// }) -// }) - - - - - - - - - - - - - - - -// +var Rental = require('../../models/rental') + +describe('Rental', function () { + var title1 = "Alien" + var overview1 = 'During its return to the earth, commercial spaceship Nostromo intercepts a distress signal from a distant planet. When a three-member team of the crew discovers a chamber containing thousands of eggs on the planet, a creature inside one of the eggs attacks an explorer. The entire crew is unaware of the impending nightmare set to descend upon them when the alien parasite planted inside its unfortunate host is birthed.' + var release_date1 = '1979-05-25' + var inventory1 = 4 + + afterEach(function () { + db.end() + }) + + describe('#getRentals', function () { + it('should return all movies', function (done) { + Rental.all(function (error, movies) { + expect(movies.length).toEqual(100) + }) + done() + }) + }) + + describe('#getRentalsShow', function () { + it('should return correct movie', function (done) { + Rental.find(title1, function (error, movie) { + expect(movie[0].title).toEqual(title1) + expect(movie[0].overview).toEqual(overview1) + expect(movie[0].release_date).toEqual(release_date1) + expect(movie[0].inventory).toEqual(inventory1) + expect(error).toBeNull + done() + }) + }) + + it('should throw an error if the movie DNE', function (done) { + Rental.find("bad title", function(error, movie) { + expect(error.message).toEqual("Could not retrieve movies") + }) + done() + }) + }) + + // describe('#sort', function () { + // it('should sort customer by name', function(done) { + // Rental.sort("name", 1, 3, function(error, customer_array) { + // expect(customer_array.length).toEqual(1) + // expect(customer_array[0].name).toEqual(customer1) + // expect(customer_array[0].registered_at).toEqual(registered_at1) + // expect(customer_array[0].address).toEqual(address1) + // expect(customer_array[0].city).toEqual(city1) + // expect(customer_array[0].state).toEqual(state1) + // expect(customer_array[0].postal_code).toEqual(postal_code1) + // expect(customer_array[0].phone).toEqual(phone1) + // expect(customer_array[0].account_credit).toEqual(account_credit1) + // expect(error).toBeNull + // }) + // done() + // }) + // + // it('should throw an error if the customer DNE', function (done) { + // Rental.sort("abcd", 1, 3, function(error, customer_array2) { + // expect(error.message).toEqual("Could not retrieve customers") + // }) + // done() + // }) + // }) +}) From b04c9e9c7a112387feece6259c1c06b540899e13 Mon Sep 17 00:00:00 2001 From: Adriana Date: Sat, 18 Jun 2016 09:43:06 -0700 Subject: [PATCH 38/93] Have all passing tests for all controllers and functions and all models and functions --- spec/controllers/customers.spec.js | 30 ++++++++++++- spec/controllers/movies.spec.js | 70 ++++++++++++++++++++++++++---- spec/models/rental.spec.js | 4 +- 3 files changed, 92 insertions(+), 12 deletions(-) diff --git a/spec/controllers/customers.spec.js b/spec/controllers/customers.spec.js index ae986e07d..f4f4693ac 100644 --- a/spec/controllers/customers.spec.js +++ b/spec/controllers/customers.spec.js @@ -56,9 +56,35 @@ describe("CustomersController", function() { var data = JSON.parse(body) expect(typeof data).toEqual('object') - // for (var record of data) { expect(Object.keys(data)).toEqual([ 'id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit' ]) - // } + done() + }) + }) + }) + + describe('#getCustomersSort', function(done) { + it('returns a success response', function(done) { + request.get(url("/sort/name?n=1&p=2"), function(error, response, body) { + expect(response.statusCode).toBe(200) + done() + }) + }) + + it("returns JSON", function(done) { + request.get(url("/sort/name?n=1&p=2"), function(error, response, body) { + expect(response.headers['content-type']).toContain('application/json') + done() + }) + }) + + it("should be an array of objects", function(done) { + request.get(url("/sort/name?n=1&p=2"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') + + for (var record of data) { + expect(Object.keys(record)).toEqual([ 'id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit' ]) + } done() }) }) diff --git a/spec/controllers/movies.spec.js b/spec/controllers/movies.spec.js index 3599420fa..8ed1ca2e3 100644 --- a/spec/controllers/movies.spec.js +++ b/spec/controllers/movies.spec.js @@ -25,15 +25,69 @@ describe("MoviesController", function() { }) it("should be an array of objects", function(done) { - request.get(url("/"), function(error, response, body) { - var data = JSON.parse(body) - expect(typeof data).toEqual('object') + request.get(url("/"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') + + for (var record of data) { + expect(Object.keys(record)).toEqual([ 'id', 'title', 'overview', 'release_date', 'inventory']) + } + done() + }) + }) + }) + + describe('#getMoviesShow', function(done) { + it('returns a success response', function(done) { + request.get(url("/Jaws"), function(error, response, body) { + expect(response.statusCode).toBe(200) + done() + }) + }) + + it("returns JSON", function(done) { + request.get(url("/Jaws"), function(error, response, body) { + expect(response.headers['content-type']).toContain('application/json') + done() + }) + }) + + it("should be an array of objects", function(done) { + request.get(url("/Jaws"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') - for (var record of data) { - expect(Object.keys(record)).toEqual([ 'id', 'title', 'overview', 'release_date', 'inventory']) - } - done() + expect(Object.keys(data)).toEqual([ 'id', 'title', 'overview', 'release_date', 'inventory']) + done() + }) }) }) + + describe('#getMoviesSort', function(done) { + it('returns a success response', function(done) { + request.get(url("/sort/title?n=1&p=2"), function(error, response, body) { + expect(response.statusCode).toBe(200) + done() + }) + }) + + it("returns JSON", function(done) { + request.get(url("/sort/title?n=1&p=2"), function(error, response, body) { + expect(response.headers['content-type']).toContain('application/json') + done() + }) + }) + + it("should be an array of objects", function(done) { + request.get(url("/sort/title?n=1&p=2"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') + + for (var record of data) { + expect(Object.keys(record)).toEqual([ 'id', 'title', 'overview', 'release_date', 'inventory']) + } + done() + }) + }) }) -}) \ No newline at end of file +}) diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js index 7710523ca..6473269cb 100644 --- a/spec/models/rental.spec.js +++ b/spec/models/rental.spec.js @@ -13,7 +13,7 @@ describe('Rental', function () { db.end() }) - describe('#getRentals', function () { + describe('#all', function () { it('should return all movies', function (done) { Rental.all(function (error, movies) { expect(movies.length).toEqual(100) @@ -22,7 +22,7 @@ describe('Rental', function () { }) }) - describe('#getRentalsShow', function () { + describe('#find', function () { it('should return correct movie', function (done) { Rental.find(title1, function (error, movie) { expect(movie[0].title).toEqual(title1) From 440cae3638b6371c6df3bb3170e14bcc50341f17 Mon Sep 17 00:00:00 2001 From: Jessica Date: Mon, 20 Jun 2016 10:33:36 -0700 Subject: [PATCH 39/93] added temporary seed data to test customer routes for current checked out movies and rental history. added route for this and isntabul test path --- db/seeds/rentals.json | 38 ++++++++++++++++++++++++++++++++++++++ package.json | 3 +-- routes/rentals.js | 2 +- 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 db/seeds/rentals.json diff --git a/db/seeds/rentals.json b/db/seeds/rentals.json new file mode 100644 index 000000000..bc316969b --- /dev/null +++ b/db/seeds/rentals.json @@ -0,0 +1,38 @@ +[ +{ +"customer_id": 1, +"movie_id": 29, +"status": true, +"return_date": "Sun Jun 19 2016 22:19:53 GMT-0700 (PDT)" +}, +{ +"customer_id": 19, +"movie_id": 69, +"status": true, +"return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" +}, +{ +"customer_id": 29, +"movie_id": 39, +"status": true, +"return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" +}, +{ +"customer_id": 29, +"movie_id": 19, +"status": true, +"return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" +}, +{ +"customer_id": 29, +"movie_id": 99, +"status": true, +"return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" +}, +{ +"customer_id": 29, +"movie_id": 89, +"status": false, +"return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" +} +] \ No newline at end of file diff --git a/package.json b/package.json index 5b382d61d..388c7bfc4 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,7 @@ "private": true, "scripts": { "start": "nodemon ./bin/www", - "test": "clear; ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/", - "db:drop": "dropdb video_store", + "test": "clear; ./node_modules/.bin/istanbul cover --include-all-sources ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/", "db:drop": "dropdb video_store", "db:create": "createdb video_store", "db:schema": "node tasks/load_schema", "db:seed": "node tasks/seed.js", diff --git a/routes/rentals.js b/routes/rentals.js index 24c113dbc..84033fdbb 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -4,6 +4,6 @@ var Controller = require('../controllers/rentals') router.get('/', Controller.getRentals) router.get('/:title', Controller.getRentalsShow) -// router.get('/:title/customers', Controller.getRentalStatus) +router.get('/customers/:id/current', Controller.getRentalsCurrent) module.exports = router From 955c5d954b635edabd08765ef4a758a74e11b6bb Mon Sep 17 00:00:00 2001 From: Jessica Date: Mon, 20 Jun 2016 11:09:34 -0700 Subject: [PATCH 40/93] findRentals method in model retrieving rentals data from temp seeded data, so route is working woooo --- controllers/customers.js | 18 ++++++++++++++++-- models/rental.js | 21 ++++++++++++++++++++- package.json | 4 +++- routes/customers.js | 2 ++ routes/rentals.js | 1 - tasks/seed.js | 5 +++++ 6 files changed, 46 insertions(+), 5 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index b95c84d0d..23cd8b7a8 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -1,4 +1,5 @@ var Customer = require('../models/customer') +var Rental = require('../models/rental') CustomersController = { locals: { @@ -17,7 +18,7 @@ CustomersController = { }) }, - getCustomersShow: function(req, res, next) { + getCustomersShow: function (req, res, next) { Customer.find(req.params.name, function(error, customer) { if(error) { var err = new Error("No such customer"); @@ -29,7 +30,7 @@ CustomersController = { }) }, - getCustomersSort: function(req, res) { + getCustomersSort: function (req, res, next) { Customer.sort(req.params.field, req.query.n, req.query.p, function(error, customer) { if (error) { var err = new Error("Error retrieving customer list:\n" + error.message); @@ -39,6 +40,19 @@ CustomersController = { res.json(customer) } }) + }, + + getRentalsCurrent: function (req, res, next) { + Rental.findRentals(req.params.id, function (error, rental) { + if (error) { + var err = new Error("Error retrieving rental list:\n" + error.message); + err.status = 500; + next(err); + } else { + console.log(rental) + res.json(rental) + } + }) } } diff --git a/models/rental.js b/models/rental.js index 52cd02cb7..8d8d03bc4 100644 --- a/models/rental.js +++ b/models/rental.js @@ -2,7 +2,13 @@ var app = require('../app') var db = app.get('db') var Movie = require('./movie') -var Rental = function () {} +var Rental = function (rental) { + this.id = rental.id + this.customer_id = rental.customer_id + this.movie_id = rental.movie_id + this.status = rental.status + this.return_date = rental.return_date +} Rental.all = function (callback) { db.movies.find (function (error, movies) { @@ -28,5 +34,18 @@ Rental.find = function (title, callback) { }) } +Rental.findRentals = function (id, callback) { + db.rentals.find({customer_id: id, status: true}, function (error, rentals) { + if (error || !rentals) { + callback(new Error("Could not retrieve rentals"), undefined) + } else { + callback(null, rentals.map (function (rental) { + // console.log(rental) + return new Rental(rental) + })) + } + }) +} + module.exports = Rental diff --git a/package.json b/package.json index 388c7bfc4..173df8b91 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "private": true, "scripts": { "start": "nodemon ./bin/www", - "test": "clear; ./node_modules/.bin/istanbul cover --include-all-sources ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/", "db:drop": "dropdb video_store", + "test": "clear; ./node_modules/.bin/istanbul cover --include-all-sources ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/", + "db:drop": "dropdb video_store", "db:create": "createdb video_store", "db:schema": "node tasks/load_schema", "db:seed": "node tasks/seed.js", @@ -22,6 +23,7 @@ "massive": "^2.3.0" }, "devDependencies": { + "istanbul": "^0.4.4", "jasmine-node": "^1.14.5", "nodemon": "^1.9.2", "request": "^2.72.0" diff --git a/routes/customers.js b/routes/customers.js index 77f5734e9..fbafd8722 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -6,6 +6,8 @@ var Controller = require('../controllers/customers') router.get('/', Controller.getCustomers) router.get('/:name', Controller.getCustomersShow) router.get('/sort/:field', Controller.getCustomersSort) +router.get('/:id/current', Controller.getRentalsCurrent) + module.exports = router diff --git a/routes/rentals.js b/routes/rentals.js index 84033fdbb..e3b17c897 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -4,6 +4,5 @@ var Controller = require('../controllers/rentals') router.get('/', Controller.getRentals) router.get('/:title', Controller.getRentalsShow) -router.get('/customers/:id/current', Controller.getRentalsCurrent) module.exports = router diff --git a/tasks/seed.js b/tasks/seed.js index a89b2340c..078e44668 100644 --- a/tasks/seed.js +++ b/tasks/seed.js @@ -5,6 +5,7 @@ var db = massive.connectSync({connectionString : connectionString}) var customers = require("../db/seeds/customers.json") var movies = require("../db/seeds/movies.json") +var rentals = require("../db/seeds/rentals.json") for (var customer of customers) { console.log(customer) @@ -16,5 +17,9 @@ for (var movie of movies) { db.movies.saveSync(movie) } +for (var rental of rentals) { + console.log(rental) + db.rentals.saveSync(rental) +} console.log("seeding done!") process.exit() From 42f00a0c237d908dccdb21a25cefa9689de43961 Mon Sep 17 00:00:00 2001 From: Jessica Date: Mon, 20 Jun 2016 11:15:13 -0700 Subject: [PATCH 41/93] rental history for customers working with temp seed data --- controllers/customers.js | 17 ++++++++++++++--- models/rental.js | 15 +++++++++++++-- routes/customers.js | 1 + 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index 23cd8b7a8..ffda84d1d 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -43,13 +43,24 @@ CustomersController = { }, getRentalsCurrent: function (req, res, next) { - Rental.findRentals(req.params.id, function (error, rental) { + Rental.findCurrent(req.params.id, function (error, rental) { if (error) { - var err = new Error("Error retrieving rental list:\n" + error.message); + var err = new Error("Error retrieving current rentals:\n" + error.message); + err.status = 500; + next(err); + } else { + res.json(rental) + } + }) + }, + + getRentalsHistory: function (req, res, next) { + Rental.findHistory(req.params.id, function (error, rental) { + if (error) { + var err = new Error("Error retrieving rental history:\n" + error.message); err.status = 500; next(err); } else { - console.log(rental) res.json(rental) } }) diff --git a/models/rental.js b/models/rental.js index 8d8d03bc4..07fcccf58 100644 --- a/models/rental.js +++ b/models/rental.js @@ -34,13 +34,24 @@ Rental.find = function (title, callback) { }) } -Rental.findRentals = function (id, callback) { +Rental.findCurrent = function (id, callback) { db.rentals.find({customer_id: id, status: true}, function (error, rentals) { if (error || !rentals) { callback(new Error("Could not retrieve rentals"), undefined) } else { callback(null, rentals.map (function (rental) { - // console.log(rental) + return new Rental(rental) + })) + } + }) +} + +Rental.findHistory = function (id, callback) { + db.rentals.find({customer_id: id}, function (error, rentals) { + if (error || !rentals) { + callback(new Error("Could not retrieve rentals"), undefined) + } else { + callback(null, rentals.map (function (rental) { return new Rental(rental) })) } diff --git a/routes/customers.js b/routes/customers.js index fbafd8722..a7ec08036 100644 --- a/routes/customers.js +++ b/routes/customers.js @@ -7,6 +7,7 @@ router.get('/', Controller.getCustomers) router.get('/:name', Controller.getCustomersShow) router.get('/sort/:field', Controller.getCustomersSort) router.get('/:id/current', Controller.getRentalsCurrent) +router.get('/:id/history', Controller.getRentalsHistory) From 2dee49d966e383222fec0fcdf0c122d90717c831 Mon Sep 17 00:00:00 2001 From: Jessica Date: Mon, 20 Jun 2016 13:26:22 -0700 Subject: [PATCH 42/93] created sql file for inner joining rentals, movies, customers. returning movie id --- controllers/movies.js | 22 +++++++++++++--------- db/rental_movie_history.sql | 14 ++++++++++++++ db/seeds/rentals.json | 6 ++++++ models/rental.js | 16 ++++++++++++++++ routes/movies.js | 2 ++ 5 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 db/rental_movie_history.sql diff --git a/controllers/movies.js b/controllers/movies.js index b04ada86f..7020fac7a 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -1,4 +1,5 @@ var Movie = require('../models/movie') +var Rental = require('../models/rental') MoviesController = { locals: { @@ -25,15 +26,6 @@ MoviesController = { next(err); } else { res.json(movie) - - // movie.getBalance(function(error, balance) { - // res.render("movies/show", { - // movie: { - // id: movie.id, - // balance: balance - // } - // }); - // }); } }) }, @@ -48,6 +40,18 @@ MoviesController = { res.json(movie) } }) + }, + + getMoviesCurrent: function (req, res, next) { + Rental.findCurrentMovies(req.params.title, function (error, movie) { + if (error) { + var err = new Error("Error retrieving current movies:\n" + error.message); + err.status = 500; + next(err); + } else { + res.json(movie) + } + }) } } diff --git a/db/rental_movie_history.sql b/db/rental_movie_history.sql new file mode 100644 index 000000000..12a64cef2 --- /dev/null +++ b/db/rental_movie_history.sql @@ -0,0 +1,14 @@ +-- SELECT movies.id, movies.title, rentals.movie_id, rentals.customer_id, customers.id +-- FROM movies +-- INNER JOIN rentals +-- ON movies.id=rentals.movie_id; + +SELECT movies.id, rentals.movie_id, rentals.customer_id +FROM movies +INNER JOIN rentals +ON movies.id=rentals.movie_id +INNER JOIN customers +ON rentals.customer_id=customers.id +WHERE title=$1; + + diff --git a/db/seeds/rentals.json b/db/seeds/rentals.json index bc316969b..b1fa3f5d3 100644 --- a/db/seeds/rentals.json +++ b/db/seeds/rentals.json @@ -12,6 +12,12 @@ "return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" }, { +"customer_id": 19, +"movie_id": 39, +"status": true, +"return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" +}, +{ "customer_id": 29, "movie_id": 39, "status": true, diff --git a/models/rental.js b/models/rental.js index 07fcccf58..9ccd7fcc2 100644 --- a/models/rental.js +++ b/models/rental.js @@ -1,6 +1,9 @@ var app = require('../app') var db = app.get('db') var Movie = require('./movie') +var Customer = require('./customer') + +// var movieHistory = require('../db/rental_movie_history') var Rental = function (rental) { this.id = rental.id @@ -58,5 +61,18 @@ Rental.findHistory = function (id, callback) { }) } +Rental.findCurrentMovies = function (title, callback) { + db.rental_movie_history([title], function (error, customers) { + console.log(customers) + if (error || !customers) { + callback(new Error("Could not retrieve rentals"), undefined) + } else { + callback(null, customers.map (function (customer) { + return new Customer(customer) + })) + } + }) +} + module.exports = Rental diff --git a/routes/movies.js b/routes/movies.js index ad4a06f8d..ed609b366 100644 --- a/routes/movies.js +++ b/routes/movies.js @@ -5,5 +5,7 @@ var Controller = require('../controllers/movies') router.get('/', Controller.getMovies) router.get('/:title', Controller.getMoviesShow) router.get('/sort/:field', Controller.getMoviesSort) +router.get('/:title/current', Controller.getMoviesCurrent) + module.exports = router From cc8267fa9b54a0bcc70bbc87b4480805a22369ad Mon Sep 17 00:00:00 2001 From: Adriana Date: Mon, 20 Jun 2016 14:21:34 -0700 Subject: [PATCH 43/93] trying to get current movies out --- controllers/movies.js | 1 - db/rental_movie_history.sql | 6 ++---- models/customer.js | 10 ++++++++++ models/rental.js | 30 +++++++++++++++++++++--------- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/controllers/movies.js b/controllers/movies.js index 7020fac7a..e0f39d83d 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -56,4 +56,3 @@ MoviesController = { } module.exports = MoviesController - diff --git a/db/rental_movie_history.sql b/db/rental_movie_history.sql index 12a64cef2..bfd7f96e0 100644 --- a/db/rental_movie_history.sql +++ b/db/rental_movie_history.sql @@ -3,12 +3,10 @@ -- INNER JOIN rentals -- ON movies.id=rentals.movie_id; -SELECT movies.id, rentals.movie_id, rentals.customer_id -FROM movies +SELECT movies.id, rentals.movie_id, rentals.customer_id, customers.id +FROM movies INNER JOIN rentals ON movies.id=rentals.movie_id INNER JOIN customers ON rentals.customer_id=customers.id WHERE title=$1; - - diff --git a/models/customer.js b/models/customer.js index 92a94888d..9e2ec84a2 100644 --- a/models/customer.js +++ b/models/customer.js @@ -35,6 +35,16 @@ Customer.find = function(name, callback) { }) } +Customer.find_by_id = function(id, callback) { + db.customers.find({id: id}, function(error, customer) { + if(error || !customer) { + callback(new Error("Customer not found"), undefined) + } else { + callback(null, new Customer(customer)) + } + }) +} + Customer.sort = function(field, n, p, callback){ db.customers.find({}, { order: field, diff --git a/models/rental.js b/models/rental.js index 9ccd7fcc2..fe7c9bf9d 100644 --- a/models/rental.js +++ b/models/rental.js @@ -62,15 +62,27 @@ Rental.findHistory = function (id, callback) { } Rental.findCurrentMovies = function (title, callback) { - db.rental_movie_history([title], function (error, customers) { - console.log(customers) - if (error || !customers) { - callback(new Error("Could not retrieve rentals"), undefined) - } else { - callback(null, customers.map (function (customer) { - return new Customer(customer) - })) - } + db.rental_movie_history([title], function (error, movies) { + console.log(movies); + db.customers.find({id: movies[0].customer_id}, function (error, custy) { + // Customer.find_by_id(customers[0].customer_id, function (error, custy) { + // console.log(custy); + if (error || !custy) { + callback(new Error("Could not retrieve rentals"), undefined) + } else { + callback(null, custy.map (function (cust) { + return new Customer(cust) + })) + } + }) + // console.log(customers[0].customer_id) + // if (error || !customers) { + // callback(new Error("Could not retrieve rentals"), undefined) + // } else { + // callback(null, customers.map (function (customer) { + // return new Customer(customer) + // })) + // } }) } From ef51688f37e8917565a634af8248d3dada7554be Mon Sep 17 00:00:00 2001 From: Adriana Date: Mon, 20 Jun 2016 15:00:52 -0700 Subject: [PATCH 44/93] Debugging movies rental history --- controllers/movies.js | 6 +++--- db/rental_movie_history.sql | 8 ++++---- models/rental.js | 19 +++++-------------- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/controllers/movies.js b/controllers/movies.js index e0f39d83d..b0b729b5d 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -43,13 +43,13 @@ MoviesController = { }, getMoviesCurrent: function (req, res, next) { - Rental.findCurrentMovies(req.params.title, function (error, movie) { + Rental.findCurrentMovies(req.params.title, function (error, customer) { if (error) { - var err = new Error("Error retrieving current movies:\n" + error.message); + var err = new Error("Error retrieving current customers:\n" + error.message); err.status = 500; next(err); } else { - res.json(movie) + res.json(customer) } }) } diff --git a/db/rental_movie_history.sql b/db/rental_movie_history.sql index bfd7f96e0..a4771ace3 100644 --- a/db/rental_movie_history.sql +++ b/db/rental_movie_history.sql @@ -3,10 +3,10 @@ -- INNER JOIN rentals -- ON movies.id=rentals.movie_id; -SELECT movies.id, rentals.movie_id, rentals.customer_id, customers.id -FROM movies -INNER JOIN rentals +SELECT movies.id, rentals.movie_id, rentals.customer_id, customers.id as customer_id, customers.name +FROM rentals +INNER JOIN movies ON movies.id=rentals.movie_id INNER JOIN customers ON rentals.customer_id=customers.id -WHERE title=$1; +WHERE movies.title=$1; diff --git a/models/rental.js b/models/rental.js index fe7c9bf9d..d9af8fc1a 100644 --- a/models/rental.js +++ b/models/rental.js @@ -51,6 +51,7 @@ Rental.findCurrent = function (id, callback) { Rental.findHistory = function (id, callback) { db.rentals.find({customer_id: id}, function (error, rentals) { + console.log(rentals); if (error || !rentals) { callback(new Error("Could not retrieve rentals"), undefined) } else { @@ -62,27 +63,17 @@ Rental.findHistory = function (id, callback) { } Rental.findCurrentMovies = function (title, callback) { - db.rental_movie_history([title], function (error, movies) { - console.log(movies); - db.customers.find({id: movies[0].customer_id}, function (error, custy) { - // Customer.find_by_id(customers[0].customer_id, function (error, custy) { - // console.log(custy); + db.rental_movie_history([title], function (error, customers) { + db.customers.find({id: customers.customer_id}, function (error, custy) { + console.log(customers); if (error || !custy) { callback(new Error("Could not retrieve rentals"), undefined) } else { callback(null, custy.map (function (cust) { - return new Customer(cust) + return new Rental(cust) })) } }) - // console.log(customers[0].customer_id) - // if (error || !customers) { - // callback(new Error("Could not retrieve rentals"), undefined) - // } else { - // callback(null, customers.map (function (customer) { - // return new Customer(customer) - // })) - // } }) } From fdeb7ce6931bfd69e1845668f6fda5f0759635b9 Mon Sep 17 00:00:00 2001 From: Jessica Date: Mon, 20 Jun 2016 15:21:31 -0700 Subject: [PATCH 45/93] one customer showing up for current rentals. --- db/rental_movie_history.sql | 4 ---- models/rental.js | 23 ++++++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/db/rental_movie_history.sql b/db/rental_movie_history.sql index a4771ace3..445e29089 100644 --- a/db/rental_movie_history.sql +++ b/db/rental_movie_history.sql @@ -1,7 +1,3 @@ --- SELECT movies.id, movies.title, rentals.movie_id, rentals.customer_id, customers.id --- FROM movies --- INNER JOIN rentals --- ON movies.id=rentals.movie_id; SELECT movies.id, rentals.movie_id, rentals.customer_id, customers.id as customer_id, customers.name FROM rentals diff --git a/models/rental.js b/models/rental.js index d9af8fc1a..5084b0ca0 100644 --- a/models/rental.js +++ b/models/rental.js @@ -51,7 +51,6 @@ Rental.findCurrent = function (id, callback) { Rental.findHistory = function (id, callback) { db.rentals.find({customer_id: id}, function (error, rentals) { - console.log(rentals); if (error || !rentals) { callback(new Error("Could not retrieve rentals"), undefined) } else { @@ -64,16 +63,18 @@ Rental.findHistory = function (id, callback) { Rental.findCurrentMovies = function (title, callback) { db.rental_movie_history([title], function (error, customers) { - db.customers.find({id: customers.customer_id}, function (error, custy) { - console.log(customers); - if (error || !custy) { - callback(new Error("Could not retrieve rentals"), undefined) - } else { - callback(null, custy.map (function (cust) { - return new Rental(cust) - })) - } - }) + for (var id of customers){ + db.customers.find({id: id.customer_id}, function (error, customers) { + console.log(id) + if (error || !customers) { + callback(new Error("Could not retrieve rentals"), undefined) + } else { + callback(null, customers.map (function (customer) { + return new Customer(customer) + })) + } + }) + } }) } From 3d331b7406982c7d9dcd715827a5cf62006628ce Mon Sep 17 00:00:00 2001 From: Jessica Date: Mon, 20 Jun 2016 16:11:08 -0700 Subject: [PATCH 46/93] finally got list of customers who currently have specific movie checked out working --- controllers/movies.js | 1 + db/rental_movie_history.sql | 2 +- models/rental.js | 17 ++++++----------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/controllers/movies.js b/controllers/movies.js index b0b729b5d..36e3a5ba0 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -44,6 +44,7 @@ MoviesController = { getMoviesCurrent: function (req, res, next) { Rental.findCurrentMovies(req.params.title, function (error, customer) { + console.log(customer) if (error) { var err = new Error("Error retrieving current customers:\n" + error.message); err.status = 500; diff --git a/db/rental_movie_history.sql b/db/rental_movie_history.sql index 445e29089..469ad5182 100644 --- a/db/rental_movie_history.sql +++ b/db/rental_movie_history.sql @@ -1,5 +1,5 @@ -SELECT movies.id, rentals.movie_id, rentals.customer_id, customers.id as customer_id, customers.name +SELECT movies.id, rentals.movie_id, rentals.customer_id, customers.id as customer_id, customers.* FROM rentals INNER JOIN movies ON movies.id=rentals.movie_id diff --git a/models/rental.js b/models/rental.js index 5084b0ca0..fb04b356e 100644 --- a/models/rental.js +++ b/models/rental.js @@ -63,17 +63,12 @@ Rental.findHistory = function (id, callback) { Rental.findCurrentMovies = function (title, callback) { db.rental_movie_history([title], function (error, customers) { - for (var id of customers){ - db.customers.find({id: id.customer_id}, function (error, customers) { - console.log(id) - if (error || !customers) { - callback(new Error("Could not retrieve rentals"), undefined) - } else { - callback(null, customers.map (function (customer) { - return new Customer(customer) - })) - } - }) + if (error || !customers) { + callback(new Error("Could not retrieve rentals"), undefined) + } else { + callback(null, customers.map(function (customer) { + return new Customer(customer) + })) } }) } From eb7550b286826440106a106bc3dd5115854c446a Mon Sep 17 00:00:00 2001 From: Adriana Date: Mon, 20 Jun 2016 16:15:10 -0700 Subject: [PATCH 47/93] Added a checkout date column for rentals --- db/setup/schema.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/setup/schema.sql b/db/setup/schema.sql index 508afd399..5f8be8e8a 100644 --- a/db/setup/schema.sql +++ b/db/setup/schema.sql @@ -26,5 +26,6 @@ CREATE TABLE rentals( customer_id int, movie_id int, status boolean, + checkout_date text, return_date text ); From 6d405c5726da209785f991a1c8a4e13f74c665a6 Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 21 Jun 2016 09:22:45 -0700 Subject: [PATCH 48/93] Cleaned up code --- controllers/movies.js | 1 - db/rental_movie_history.sql | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/controllers/movies.js b/controllers/movies.js index 36e3a5ba0..b0b729b5d 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -44,7 +44,6 @@ MoviesController = { getMoviesCurrent: function (req, res, next) { Rental.findCurrentMovies(req.params.title, function (error, customer) { - console.log(customer) if (error) { var err = new Error("Error retrieving current customers:\n" + error.message); err.status = 500; diff --git a/db/rental_movie_history.sql b/db/rental_movie_history.sql index 469ad5182..29dfeb0da 100644 --- a/db/rental_movie_history.sql +++ b/db/rental_movie_history.sql @@ -1,5 +1,5 @@ -SELECT movies.id, rentals.movie_id, rentals.customer_id, customers.id as customer_id, customers.* +SELECT movies.id, rentals.movie_id, rentals.customer_id, customers.* FROM rentals INNER JOIN movies ON movies.id=rentals.movie_id From e1880ae0bbe07888c7d3161c76147af5c79823f7 Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 21 Jun 2016 09:58:26 -0700 Subject: [PATCH 49/93] Added controller testing and adding coverage to git ignore --- .gitignore | 1 + spec/controllers/customers.spec.js | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 646ac519e..062fe0c62 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store node_modules/ +/coverage diff --git a/spec/controllers/customers.spec.js b/spec/controllers/customers.spec.js index f4f4693ac..5d0a3c13d 100644 --- a/spec/controllers/customers.spec.js +++ b/spec/controllers/customers.spec.js @@ -1,8 +1,7 @@ var request = require("request") - +var app = require("../../app.js") var baseUrl = "http://localhost:3000" - describe("CustomersController", function() { var url = function(endpoint) { return baseUrl + "/customers" + endpoint @@ -16,6 +15,13 @@ describe("CustomersController", function() { }) }) + it("returns the body data", function(done) { + request.get(url("/Shelley Rocha"), function(error, response, body) { + expect(response.body).toBe('{"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"}') + done() + }) + }) + it("returns JSON", function(done) { request.get(url("/"), function(error, response, body) { expect(response.headers['content-type']).toContain('application/json') From fd5b67c3543d7e94f2398e9baeb17c3ed83513f8 Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 21 Jun 2016 10:21:06 -0700 Subject: [PATCH 50/93] Added model testing --- spec/models/rental.spec.js | 73 +++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js index 6473269cb..a9194b598 100644 --- a/spec/models/rental.spec.js +++ b/spec/models/rental.spec.js @@ -42,28 +42,53 @@ describe('Rental', function () { }) }) - // describe('#sort', function () { - // it('should sort customer by name', function(done) { - // Rental.sort("name", 1, 3, function(error, customer_array) { - // expect(customer_array.length).toEqual(1) - // expect(customer_array[0].name).toEqual(customer1) - // expect(customer_array[0].registered_at).toEqual(registered_at1) - // expect(customer_array[0].address).toEqual(address1) - // expect(customer_array[0].city).toEqual(city1) - // expect(customer_array[0].state).toEqual(state1) - // expect(customer_array[0].postal_code).toEqual(postal_code1) - // expect(customer_array[0].phone).toEqual(phone1) - // expect(customer_array[0].account_credit).toEqual(account_credit1) - // expect(error).toBeNull - // }) - // done() - // }) - // - // it('should throw an error if the customer DNE', function (done) { - // Rental.sort("abcd", 1, 3, function(error, customer_array2) { - // expect(error.message).toEqual("Could not retrieve customers") - // }) - // done() - // }) - // }) + describe("#findHistory", function () { + it("should return history rentals for a customer", function (done) { + Rental.findHistory(1, function (error, customer) { + expect(customer[0].customer_id).toEqual(1) + expect(customer[0].movie_id).toEqual(29) + expect(customer[0].status).toEqual(true) + expect(customer[0].return_date).toEqual('Sun Jun 19 2016 22:19:53 GMT-0700 (PDT)') + done() + }) + }) + + it('should throw an error if no rentals found', function (done) { + Rental.findHistory(300, function(error, movie) { + expect(error.message).toEqual("Could not retrieve rentals") + }) + done() + }) + + it('if customer has no rentals', function (done) { + Rental.findHistory(200, function(error, movie) { + expect(error.message).toEqual([]) + }) + done() + }) + }) + + describe("#findCurrent", function () { + it("should return current rentals for a customer", function (done) { + Rental.findCurrent(29, function (error, customer) { + expect(customer.length).toEqual(3) + expect(customer[0].customer_id).toEqual(29) + done() + }) + }) + + it('should throw an error if no rentals found', function (done) { + Rental.findCurrent(300, function(error, movie) { + expect(error.message).toEqual("Could not retrieve rentals") + }) + done() + }) + + it('if customer has no rentals', function (done) { + Rental.findCurrent(200, function(error, movie) { + expect(error.message).toEqual([]) + }) + done() + }) + }) }) From 51fbee513cea16f9654afd0a655d3bb3fc91823c Mon Sep 17 00:00:00 2001 From: Jessica Date: Tue, 21 Jun 2016 13:57:21 -0700 Subject: [PATCH 51/93] writing tests for rentals, working on negative tests --- spec/controllers/customers.spec.js | 3 +-- spec/controllers/movies.spec.js | 3 +-- spec/models/customer.spec.js | 8 +++--- spec/models/movie.spec.js | 8 +++--- spec/models/rental.spec.js | 43 +++++++++++++++--------------- 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/spec/controllers/customers.spec.js b/spec/controllers/customers.spec.js index 5d0a3c13d..206c6f457 100644 --- a/spec/controllers/customers.spec.js +++ b/spec/controllers/customers.spec.js @@ -61,8 +61,7 @@ describe("CustomersController", function() { request.get(url("/Curran Stout"), function(error, response, body) { var data = JSON.parse(body) expect(typeof data).toEqual('object') - - expect(Object.keys(data)).toEqual([ 'id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit' ]) + expect(Object.keys(data)).toEqual([ 'id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit' ]) done() }) }) diff --git a/spec/controllers/movies.spec.js b/spec/controllers/movies.spec.js index 8ed1ca2e3..28a408928 100644 --- a/spec/controllers/movies.spec.js +++ b/spec/controllers/movies.spec.js @@ -56,8 +56,7 @@ describe("MoviesController", function() { request.get(url("/Jaws"), function(error, response, body) { var data = JSON.parse(body) expect(typeof data).toEqual('object') - - expect(Object.keys(data)).toEqual([ 'id', 'title', 'overview', 'release_date', 'inventory']) + expect(Object.keys(data)).toEqual([ 'id', 'title', 'overview', 'release_date', 'inventory']) done() }) }) diff --git a/spec/models/customer.spec.js b/spec/models/customer.spec.js index e5309c4a9..db2d7418e 100644 --- a/spec/models/customer.spec.js +++ b/spec/models/customer.spec.js @@ -21,8 +21,8 @@ describe('Customer', function () { it('should return all customers', function (done) { Customer.all(function (error, customers) { expect(customers.length).toEqual(200) + done() }) - done() }) }) @@ -45,8 +45,8 @@ describe('Customer', function () { it('should throw an error if the customer DNE', function (done) { Customer.find("person", function(error, customer) { expect(error.message).toEqual("Customer not found") + done() }) - done() }) }) @@ -63,15 +63,15 @@ describe('Customer', function () { expect(customer_array[0].phone).toEqual(phone1) expect(customer_array[0].account_credit).toEqual(account_credit1) expect(error).toBeNull + done() }) - done() }) it('should throw an error if the customer DNE', function (done) { Customer.sort("abcd", 1, 3, function(error, customer_array2) { expect(error.message).toEqual("Could not retrieve customers") + done() }) - done() }) }) }) diff --git a/spec/models/movie.spec.js b/spec/models/movie.spec.js index 6e1733b1e..877f8a9d7 100644 --- a/spec/models/movie.spec.js +++ b/spec/models/movie.spec.js @@ -17,8 +17,8 @@ describe('Movie', function () { it('should return all movies', function (done) { Movie.all(function (error, movies) { expect(movies.length).toEqual(100) + done() }) - done() }) }) @@ -37,8 +37,8 @@ describe('Movie', function () { it('should throw an error if the movie DNE', function (done) { Movie.find("bad title", function(error, customer) { expect(error.message).toEqual("movie not found") + done() }) - done() }) }) @@ -50,15 +50,15 @@ describe('Movie', function () { expect(movie_array[0].overview).toEqual(overview1) expect(movie_array[0].release_date).toEqual(release_date1) expect(movie_array[0].inventory).toEqual(inventory1) + done() }) - done() }) it('should throw an error if the customer DNE', function (done) { Movie.sort("bad title", 1, 3, function(error, movie) { expect(error.message).toEqual("Could not retrieve movies") + done() }) - done() }) }) }) diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js index a9194b598..3229b3225 100644 --- a/spec/models/rental.spec.js +++ b/spec/models/rental.spec.js @@ -17,8 +17,8 @@ describe('Rental', function () { it('should return all movies', function (done) { Rental.all(function (error, movies) { expect(movies.length).toEqual(100) + done() }) - done() }) }) @@ -34,12 +34,12 @@ describe('Rental', function () { }) }) - it('should throw an error if the movie DNE', function (done) { - Rental.find("bad title", function(error, movie) { - expect(error.message).toEqual("Could not retrieve movies") - }) - done() - }) + // it('should throw an error if the movie DNE', function (done) { + // Rental.find("bad title", function(error, movie) { + // expect(error.message).toEqual("Could not retrieve movies") + // done() + // }) + // }) }) describe("#findHistory", function () { @@ -53,18 +53,19 @@ describe('Rental', function () { }) }) - it('should throw an error if no rentals found', function (done) { - Rental.findHistory(300, function(error, movie) { - expect(error.message).toEqual("Could not retrieve rentals") - }) - done() - }) + // it('should throw an error if no rentals found', function (done) { + // Rental.findHistory(300, function(error, movie) { + // console.log(movie) + // expect(error.message).toEqual("Could not retrieve rentals") + // done() + // }) + // }) it('if customer has no rentals', function (done) { Rental.findHistory(200, function(error, movie) { expect(error.message).toEqual([]) + done() }) - done() }) }) @@ -77,18 +78,18 @@ describe('Rental', function () { }) }) - it('should throw an error if no rentals found', function (done) { - Rental.findCurrent(300, function(error, movie) { - expect(error.message).toEqual("Could not retrieve rentals") - }) - done() - }) + // it('should throw an error if no rentals found', function (done) { + // Rental.findCurrent(300, function(error, movie) { + // expect(error.message).toEqual("Could not retrieve rentals") + // done() + // }) + // }) it('if customer has no rentals', function (done) { Rental.findCurrent(200, function(error, movie) { expect(error.message).toEqual([]) + done() }) - done() }) }) }) From d474782419535efffb0fd9c4b6f084f72ce37459 Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 21 Jun 2016 14:35:00 -0700 Subject: [PATCH 52/93] Added negative tests --- spec/models/rental.spec.js | 39 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js index 3229b3225..7330e4d75 100644 --- a/spec/models/rental.spec.js +++ b/spec/models/rental.spec.js @@ -34,12 +34,12 @@ describe('Rental', function () { }) }) - // it('should throw an error if the movie DNE', function (done) { - // Rental.find("bad title", function(error, movie) { - // expect(error.message).toEqual("Could not retrieve movies") - // done() - // }) - // }) + it('should throw an error if the movie DNE', function (done) { + Rental.find("bad title", function(error, movie) { + expect(error.message).toEqual("Could not retrieve movies") + done() + }) + }) }) describe("#findHistory", function () { @@ -53,17 +53,16 @@ describe('Rental', function () { }) }) - // it('should throw an error if no rentals found', function (done) { - // Rental.findHistory(300, function(error, movie) { - // console.log(movie) - // expect(error.message).toEqual("Could not retrieve rentals") - // done() - // }) - // }) + it('should throw an error if no rentals found', function (done) { + Rental.findHistory(300, function(error, movie) { + expect(error).toEqual(null) + done() + }) + }) it('if customer has no rentals', function (done) { Rental.findHistory(200, function(error, movie) { - expect(error.message).toEqual([]) + expect(error).toEqual(null) done() }) }) @@ -78,12 +77,12 @@ describe('Rental', function () { }) }) - // it('should throw an error if no rentals found', function (done) { - // Rental.findCurrent(300, function(error, movie) { - // expect(error.message).toEqual("Could not retrieve rentals") - // done() - // }) - // }) + it('should throw an error if no rentals found', function (done) { + Rental.findCurrent(300, function(error, movie) { + expect(error).toEqual(null) + done() + }) + }) it('if customer has no rentals', function (done) { Rental.findCurrent(200, function(error, movie) { From 675cbb0c82e83677dd4411146ba15c1e5a88dd6b Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 21 Jun 2016 14:41:18 -0700 Subject: [PATCH 53/93] Cleaned up rental spec code, if using find, no callback error is given --- models/rental.js | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/models/rental.js b/models/rental.js index fb04b356e..8a6a7abce 100644 --- a/models/rental.js +++ b/models/rental.js @@ -15,13 +15,9 @@ var Rental = function (rental) { Rental.all = function (callback) { db.movies.find (function (error, movies) { - if (error || !movies) { - callback(new Error("Could not retrieve movies"), undefined) - } else { - callback(null, movies.map (function (movie) { - return new Movie(movie) - })) - } + callback(null, movies.map (function (movie) { + return new Movie(movie) + })) }) } @@ -39,25 +35,17 @@ Rental.find = function (title, callback) { Rental.findCurrent = function (id, callback) { db.rentals.find({customer_id: id, status: true}, function (error, rentals) { - if (error || !rentals) { - callback(new Error("Could not retrieve rentals"), undefined) - } else { - callback(null, rentals.map (function (rental) { - return new Rental(rental) - })) - } + callback(null, rentals.map (function (rental) { + return new Rental(rental) + })) }) } Rental.findHistory = function (id, callback) { db.rentals.find({customer_id: id}, function (error, rentals) { - if (error || !rentals) { - callback(new Error("Could not retrieve rentals"), undefined) - } else { - callback(null, rentals.map (function (rental) { - return new Rental(rental) - })) - } + callback(null, rentals.map (function (rental) { + return new Rental(rental) + })) }) } From 0a0a40817cfe660984c36f976df355233df062c3 Mon Sep 17 00:00:00 2001 From: Jessica Date: Tue, 21 Jun 2016 14:42:16 -0700 Subject: [PATCH 54/93] working on get currently checked out movies customers --- controllers/rentals.js | 16 ++++++++++++++-- models/rental.js | 4 ++-- routes/rentals.js | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index 354748951..ea4e1b512 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -5,7 +5,7 @@ RentalsController = { title: 'RENTALS RENTALS RENTALS' }, - getRentals: function(req, res) { + getRentals: function(req, res, next) { Rental.all (function (error, movies) { if (error) { var err = new Error("Error retrieving rental list:\n" + error.message); @@ -27,7 +27,19 @@ RentalsController = { res.json(rental) } }) - } + }, + + // getRentalsCustomers:function(req, res, next) { + // Rental.find (req.params.title, function(error, rental) { + // if (error) { + // var err = new Error("No such rentals"); + // err.status = 404; + // next(err); + // } else { + // res.json(rental) + // } + // }) + // } } module.exports = RentalsController diff --git a/models/rental.js b/models/rental.js index fb04b356e..a145f829c 100644 --- a/models/rental.js +++ b/models/rental.js @@ -31,7 +31,7 @@ Rental.find = function (title, callback) { callback(new Error("Could not retrieve movies"), undefined) } else { callback(null, movies.map (function (movie) { - return new Movie(movie) + return new Movie(movie) })) } }) @@ -43,7 +43,7 @@ Rental.findCurrent = function (id, callback) { callback(new Error("Could not retrieve rentals"), undefined) } else { callback(null, rentals.map (function (rental) { - return new Rental(rental) + return new Rental(rental) })) } }) diff --git a/routes/rentals.js b/routes/rentals.js index e3b17c897..213d9217c 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -4,5 +4,6 @@ var Controller = require('../controllers/rentals') router.get('/', Controller.getRentals) router.get('/:title', Controller.getRentalsShow) +// router.get('/:title/customers', Controller.getRentalsCustomers) module.exports = router From 64f37a08a6f3ae19a9b9bdd03132f6d2d6fcb649 Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 21 Jun 2016 14:50:05 -0700 Subject: [PATCH 55/93] Took out error handling because no errors passed when using the .find in massivejs, if nothing found, it returns null --- models/customer.js | 16 ++++------------ models/movie.js | 10 +++------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/models/customer.js b/models/customer.js index 9e2ec84a2..70e9b10ad 100644 --- a/models/customer.js +++ b/models/customer.js @@ -15,13 +15,9 @@ var Customer = function (customer) { Customer.all = function (callback) { db.customers.find (function (error, customers) { - if (error || !customers) { - callback(error || new Error("Could not retrieve customers"), undefined) - } else { - callback(null, customers.map (function (customer) { - return new Customer(customer) - })) - } + callback(null, customers.map (function (customer) { + return new Customer(customer) + })) }) } @@ -37,11 +33,7 @@ Customer.find = function(name, callback) { Customer.find_by_id = function(id, callback) { db.customers.find({id: id}, function(error, customer) { - if(error || !customer) { - callback(new Error("Customer not found"), undefined) - } else { - callback(null, new Customer(customer)) - } + callback(null, new Customer(customer)) }) } diff --git a/models/movie.js b/models/movie.js index 0d31cc9ce..d275bdd1c 100644 --- a/models/movie.js +++ b/models/movie.js @@ -11,13 +11,9 @@ var Movie = function (movie) { Movie.all = function (callback) { db.movies.find (function (error, movies) { - if (error || !movies) { - callback(new Error("Could not retrieve movies"), undefined) - } else { - callback(null, movies.map (function (movie) { - return new Movie(movie) - })) - } + callback(null, movies.map (function (movie) { + return new Movie(movie) + })) }) } From 4d4b7e750c63564fd50d9c610ce89451fe7a6a38 Mon Sep 17 00:00:00 2001 From: Jessica Date: Tue, 21 Jun 2016 15:01:46 -0700 Subject: [PATCH 56/93] finished tests for rentals model so far --- models/rental.js | 10 +++------- spec/models/rental.spec.js | 29 ++++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/models/rental.js b/models/rental.js index bf117ef84..b35d36b36 100644 --- a/models/rental.js +++ b/models/rental.js @@ -51,13 +51,9 @@ Rental.findHistory = function (id, callback) { Rental.findCurrentMovies = function (title, callback) { db.rental_movie_history([title], function (error, customers) { - if (error || !customers) { - callback(new Error("Could not retrieve rentals"), undefined) - } else { - callback(null, customers.map(function (customer) { - return new Customer(customer) - })) - } + callback(null, customers.map(function (customer) { + return new Customer(customer) + })) }) } diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js index 7330e4d75..fd9afb301 100644 --- a/spec/models/rental.spec.js +++ b/spec/models/rental.spec.js @@ -86,9 +86,36 @@ describe('Rental', function () { it('if customer has no rentals', function (done) { Rental.findCurrent(200, function(error, movie) { - expect(error.message).toEqual([]) + expect(error).toEqual(null) done() }) }) }) + + describe("#findCurrentMovies", function () { + it("should return current customers currently renting a movie", function (done) { + Rental.findCurrentMovies('Die Hard', function (error, customers) { + expect(customers.length).toEqual(2) + expect(customers[0].id).toEqual(19) + done() + }) + }) + + it('should throw an error if no rentals found', function (done) { + Rental.findCurrentMovies("bad title", function(error, movie) { + console.log(error) + expect(error).toEqual(null) + done() + }) + }) + + // it('if customer has no rentals', function (done) { + // Rental.findCurrent(200, function(error, movie) { + // expect(error.message).toEqual([]) + // done() + // }) + // }) + }) + + }) From 4651ad486e6d0d0ee57eb8e540e3fea0a7aa204d Mon Sep 17 00:00:00 2001 From: Jessica Date: Tue, 21 Jun 2016 15:19:06 -0700 Subject: [PATCH 57/93] finished tests for customer model --- models/customer.js | 6 ------ spec/controllers/index.spec.js | 1 + spec/models/customer.spec.js | 16 ---------------- spec/models/rental.spec.js | 8 -------- 4 files changed, 1 insertion(+), 30 deletions(-) diff --git a/models/customer.js b/models/customer.js index 70e9b10ad..4977b7599 100644 --- a/models/customer.js +++ b/models/customer.js @@ -31,12 +31,6 @@ Customer.find = function(name, callback) { }) } -Customer.find_by_id = function(id, callback) { - db.customers.find({id: id}, function(error, customer) { - callback(null, new Customer(customer)) - }) -} - Customer.sort = function(field, n, p, callback){ db.customers.find({}, { order: field, diff --git a/spec/controllers/index.spec.js b/spec/controllers/index.spec.js index e4151d267..79acc50f2 100644 --- a/spec/controllers/index.spec.js +++ b/spec/controllers/index.spec.js @@ -1,4 +1,5 @@ var request = require('request') +var app = require("../../app.js") var base_url = "http://localhost:3000/" describe("Endpoint at /", function () { diff --git a/spec/models/customer.spec.js b/spec/models/customer.spec.js index db2d7418e..0a4ea63fb 100644 --- a/spec/models/customer.spec.js +++ b/spec/models/customer.spec.js @@ -75,19 +75,3 @@ describe('Customer', function () { }) }) }) - - - - - - - - - - - - - - - -// diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js index fd9afb301..efcc86d75 100644 --- a/spec/models/rental.spec.js +++ b/spec/models/rental.spec.js @@ -103,18 +103,10 @@ describe('Rental', function () { it('should throw an error if no rentals found', function (done) { Rental.findCurrentMovies("bad title", function(error, movie) { - console.log(error) expect(error).toEqual(null) done() }) }) - - // it('if customer has no rentals', function (done) { - // Rental.findCurrent(200, function(error, movie) { - // expect(error.message).toEqual([]) - // done() - // }) - // }) }) From 9e37fb457932687ffc5df6fe21614e35a518cea5 Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 21 Jun 2016 16:15:14 -0700 Subject: [PATCH 58/93] Added more seeding data, added movies route --- db/seeds/rentals.json | 14 +++++++++++++- routes/movies.js | 2 +- sudo | 0 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 sudo diff --git a/db/seeds/rentals.json b/db/seeds/rentals.json index b1fa3f5d3..c021ca52d 100644 --- a/db/seeds/rentals.json +++ b/db/seeds/rentals.json @@ -36,9 +36,21 @@ "return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" }, { +"customer_id": 28, +"movie_id": 89, +"status": false, +"return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" +}, +{ +"customer_id": 27, +"movie_id": 89, +"status": true, +"return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" +}, +{ "customer_id": 29, "movie_id": 89, "status": false, "return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" } -] \ No newline at end of file +] diff --git a/routes/movies.js b/routes/movies.js index ed609b366..02314160d 100644 --- a/routes/movies.js +++ b/routes/movies.js @@ -6,6 +6,6 @@ router.get('/', Controller.getMovies) router.get('/:title', Controller.getMoviesShow) router.get('/sort/:field', Controller.getMoviesSort) router.get('/:title/current', Controller.getMoviesCurrent) - +router.get('/:title/history/sort/:field', Controller.getMoviesCurrent) module.exports = router diff --git a/sudo b/sudo new file mode 100644 index 000000000..e69de29bb From 3724763aab92d45ad120f60a36844bc7cd738006 Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 21 Jun 2016 16:29:00 -0700 Subject: [PATCH 59/93] Added a new sql file to query customer rental history, added a new route for movies, added a new function for movies controller, added the model rental that queried the sql file, it effing works, we are amazing --- controllers/movies.js | 12 ++++++++++++ db/customer_rental_history.sql | 9 +++++++++ models/rental.js | 8 ++++++++ routes/movies.js | 2 +- 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 db/customer_rental_history.sql diff --git a/controllers/movies.js b/controllers/movies.js index b0b729b5d..836833c62 100644 --- a/controllers/movies.js +++ b/controllers/movies.js @@ -52,6 +52,18 @@ MoviesController = { res.json(customer) } }) + }, + + getMoviesHistory: function (req, res, next) { + Rental.findHistoryMovies(req.params.title, function (error, customers) { + if (error) { + var err = new Error("Error retrieving rental history:\n" + error.message); + err.status = 500; + next(err); + } else { + res.json(customers) + } + }) } } diff --git a/db/customer_rental_history.sql b/db/customer_rental_history.sql new file mode 100644 index 000000000..77b2fcac8 --- /dev/null +++ b/db/customer_rental_history.sql @@ -0,0 +1,9 @@ + +SELECT movies.id, rentals.movie_id, rentals.customer_id, rentals.status, customers.* +FROM rentals +INNER JOIN movies +ON movies.id=rentals.movie_id +INNER JOIN customers +ON rentals.customer_id=customers.id +WHERE movies.title=$1 AND rentals.status=false +ORDER BY customers.name; diff --git a/models/rental.js b/models/rental.js index b35d36b36..8f1ed553c 100644 --- a/models/rental.js +++ b/models/rental.js @@ -57,5 +57,13 @@ Rental.findCurrentMovies = function (title, callback) { }) } +Rental.findHistoryMovies = function (title, callback) { + db.customer_rental_history([title], function (error, customers) { + callback(null, customers.map(function (customer) { + return new Customer(customer) + })) + }) +} + module.exports = Rental diff --git a/routes/movies.js b/routes/movies.js index 02314160d..aad0e146d 100644 --- a/routes/movies.js +++ b/routes/movies.js @@ -6,6 +6,6 @@ router.get('/', Controller.getMovies) router.get('/:title', Controller.getMoviesShow) router.get('/sort/:field', Controller.getMoviesSort) router.get('/:title/current', Controller.getMoviesCurrent) -router.get('/:title/history/sort/:field', Controller.getMoviesCurrent) +router.get('/:title/history/sort/name', Controller.getMoviesHistory) module.exports = router From 2911550d77b2775c019c2147820408732b89e537 Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 21 Jun 2016 20:54:16 -0700 Subject: [PATCH 60/93] Added an index controller so route testing would be at 100% --- controllers/index.js | 11 +++++++ package.json | 2 +- routes/index.js | 5 ++- spec/controllers/movies.spec.js | 56 +++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 controllers/index.js diff --git a/controllers/index.js b/controllers/index.js new file mode 100644 index 000000000..e379e8343 --- /dev/null +++ b/controllers/index.js @@ -0,0 +1,11 @@ +IndexController = { + locals: { + title: 'INDEX INDEX INDEX' + }, + + getIndex: function(req, res) { + res.status(200).json({whatevs: 'whatevs!!!'}) + } +} + +module.exports = IndexController diff --git a/package.json b/package.json index 173df8b91..42f1d11d7 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "start": "nodemon ./bin/www", - "test": "clear; ./node_modules/.bin/istanbul cover --include-all-sources ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/", + "test": "clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/", "db:drop": "dropdb video_store", "db:create": "createdb video_store", "db:schema": "node tasks/load_schema", diff --git a/routes/index.js b/routes/index.js index 7198e54e0..638c5d715 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,8 +1,7 @@ var express = require('express') var router = express.Router() +var Controller = require('../controllers/index') -router.get('/', function(req, res, next) { - res.status(200).json({whatevs: 'whatevs!!!'}) -}) +router.get('/', Controller.getIndex) module.exports = router diff --git a/spec/controllers/movies.spec.js b/spec/controllers/movies.spec.js index 28a408928..a2cef07f2 100644 --- a/spec/controllers/movies.spec.js +++ b/spec/controllers/movies.spec.js @@ -89,4 +89,60 @@ describe("MoviesController", function() { }) }) }) + + describe('#getMoviesCurrent', function(done) { + it('returns a success response', function(done) { + request.get(url("/Die Hard/current"), function(error, response, body) { + expect(response.statusCode).toBe(200) + done() + }) + }) + + it("returns JSON", function(done) { + request.get(url("/Die Hard/current"), function(error, response, body) { + expect(response.headers['content-type']).toContain('application/json') + done() + }) + }) + + it("should be an array of objects", function(done) { + request.get(url("/Die Hard/current"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') + + for (var record of data) { + expect(Object.keys(record)).toEqual(['id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit']) + } + done() + }) + }) + }) + + describe('#getMoviesHistory', function(done) { + it('returns a success response', function(done) { + request.get(url("/The Guns of Navarone/history/sort/name"), function(error, response, body) { + expect(response.statusCode).toBe(200) + done() + }) + }) + + it("returns JSON", function(done) { + request.get(url("/The Guns of Navarone/history/sort/name"), function(error, response, body) { + expect(response.headers['content-type']).toContain('application/json') + done() + }) + }) + + it("should be an array of objects", function(done) { + request.get(url("/The Guns of Navarone/history/sort/name"), function(error, response, body) { + var data = JSON.parse(body) + expect(typeof data).toEqual('object') + + for (var record of data) { + expect(Object.keys(record)).toEqual(['id', 'name', 'registered_at', 'address', 'city', 'state', 'postal_code', 'phone', 'account_credit']) + } + done() + }) + }) + }) }) From 3a665c27088a32525dc62d471b40bb54c5350c5e Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 21 Jun 2016 21:43:53 -0700 Subject: [PATCH 61/93] Added current rentals and started on post --- controllers/index.js | 4 ++++ controllers/rentals.js | 34 +++++++++++++++++++++++----------- db/find_current_rentals.sql | 8 ++++++++ models/rental.js | 17 +++++++++++++++++ routes/index.js | 1 + routes/rentals.js | 4 +++- 6 files changed, 56 insertions(+), 12 deletions(-) create mode 100644 db/find_current_rentals.sql diff --git a/controllers/index.js b/controllers/index.js index e379e8343..d86e99224 100644 --- a/controllers/index.js +++ b/controllers/index.js @@ -5,6 +5,10 @@ IndexController = { getIndex: function(req, res) { res.status(200).json({whatevs: 'whatevs!!!'}) + }, + + getZomg: function(req, res) { + res.status(200).json({it_works: 'Yeah MF!!!'}) } } diff --git a/controllers/rentals.js b/controllers/rentals.js index ea4e1b512..85adf2636 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -29,17 +29,29 @@ RentalsController = { }) }, - // getRentalsCustomers:function(req, res, next) { - // Rental.find (req.params.title, function(error, rental) { - // if (error) { - // var err = new Error("No such rentals"); - // err.status = 404; - // next(err); - // } else { - // res.json(rental) - // } - // }) - // } + getRentalsCustomers:function(req, res, next) { + Rental.find_customers (req.params.title, function(error, customer) { + if (error) { + var err = new Error("No such customers"); + err.status = 404; + next(err); + } else { + res.json(customer) + } + }) + }, + + postCheckout:function(req, res, next) { + Rental.newRental (req.params.title, function(error, rental) { + if (error) { + var err = new Error("Can't rent out"); + err.status = 404; + next(err); + } else { + res.json(rental) + } + }) + } } module.exports = RentalsController diff --git a/db/find_current_rentals.sql b/db/find_current_rentals.sql new file mode 100644 index 000000000..96928fe65 --- /dev/null +++ b/db/find_current_rentals.sql @@ -0,0 +1,8 @@ + +SELECT movies.id, rentals.movie_id, rentals.customer_id, rentals.status, customers.* +FROM rentals +INNER JOIN movies +ON movies.id=rentals.movie_id +INNER JOIN customers +ON rentals.customer_id=customers.id +WHERE movies.title=$1 AND rentals.status=true diff --git a/models/rental.js b/models/rental.js index 8f1ed553c..524990ae4 100644 --- a/models/rental.js +++ b/models/rental.js @@ -2,6 +2,7 @@ var app = require('../app') var db = app.get('db') var Movie = require('./movie') var Customer = require('./customer') +var Rental = require('./rental') // var movieHistory = require('../db/rental_movie_history') @@ -65,5 +66,21 @@ Rental.findHistoryMovies = function (title, callback) { }) } +Rental.find_customers = function (title, callback) { + db.find_current_rentals([title], function (error, customers) { + callback(null, customers.map(function (customer) { + return new Customer(customer) + })) + }) +} + +Rental.newRental = function (title, callback) { + db.save({}, function (error, rentals) { + callback(null, rentals.map(function (rental) { + return new Rental(rental) + })) + }) +} + module.exports = Rental diff --git a/routes/index.js b/routes/index.js index 638c5d715..260e1ba93 100644 --- a/routes/index.js +++ b/routes/index.js @@ -3,5 +3,6 @@ var router = express.Router() var Controller = require('../controllers/index') router.get('/', Controller.getIndex) +router.get('/zomg', Controller.getZomg) module.exports = router diff --git a/routes/rentals.js b/routes/rentals.js index 213d9217c..cf07a517f 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -4,6 +4,8 @@ var Controller = require('../controllers/rentals') router.get('/', Controller.getRentals) router.get('/:title', Controller.getRentalsShow) -// router.get('/:title/customers', Controller.getRentalsCustomers) +router.get('/:title/customers', Controller.getRentalsCustomers) + +router.post('/:title/checkout', Controller.postCheckout) module.exports = router From ffa61bc178c18577f01cc4b758fbcebc9880bbfa Mon Sep 17 00:00:00 2001 From: Adriana Date: Tue, 21 Jun 2016 22:10:54 -0700 Subject: [PATCH 62/93] Adding post route --- controllers/rentals.js | 4 ++-- models/rental.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index 85adf2636..61ac42040 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -42,13 +42,13 @@ RentalsController = { }, postCheckout:function(req, res, next) { - Rental.newRental (req.params.title, function(error, rental) { + Rental.newRental (req.params.title, req.params.customer_id, function(error) { if (error) { var err = new Error("Can't rent out"); err.status = 404; next(err); } else { - res.json(rental) + res.status(200) } }) } diff --git a/models/rental.js b/models/rental.js index 524990ae4..47387d6a0 100644 --- a/models/rental.js +++ b/models/rental.js @@ -74,11 +74,11 @@ Rental.find_customers = function (title, callback) { }) } -Rental.newRental = function (title, callback) { - db.save({}, function (error, rentals) { - callback(null, rentals.map(function (rental) { - return new Rental(rental) - })) +Rental.newRental = function (title, cust_id, callback) { + Rental.find(title, function(error, movie) { + db.rentals.save({customer_id: cust_id, movie_id: movie.id, status: true, checkout_date: (new Date()).toString()}, function (err, response) { + callback(err) + }) }) } From 2e9d342af36dfe7b91531c43275e3f29d42256df Mon Sep 17 00:00:00 2001 From: Adriana Date: Wed, 22 Jun 2016 13:00:46 -0700 Subject: [PATCH 63/93] Working on checkout posting data --- controllers/rentals.js | 2 +- models/rental.js | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index 61ac42040..2e83d6d17 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -48,7 +48,7 @@ RentalsController = { err.status = 404; next(err); } else { - res.status(200) + res.json({checkout: "Success, you checked out, you fancy."}) } }) } diff --git a/models/rental.js b/models/rental.js index 47387d6a0..665cccd6b 100644 --- a/models/rental.js +++ b/models/rental.js @@ -76,9 +76,7 @@ Rental.find_customers = function (title, callback) { Rental.newRental = function (title, cust_id, callback) { Rental.find(title, function(error, movie) { - db.rentals.save({customer_id: cust_id, movie_id: movie.id, status: true, checkout_date: (new Date()).toString()}, function (err, response) { - callback(err) - }) + db.rentals.saveSync({customer_id: cust_id, movie_id: movie.id, status: true, checkout_date: (new Date()).toString()}) }) } From 5d5624f28c4d9f4e0df0a814fcb352302f742e4b Mon Sep 17 00:00:00 2001 From: Jessica Date: Wed, 22 Jun 2016 13:38:26 -0700 Subject: [PATCH 64/93] post to checkout working. we fancy! saving to rentals database as checkout status TRUE --- controllers/rentals.js | 3 ++- models/rental.js | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index 2e83d6d17..d4089d205 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -42,7 +42,8 @@ RentalsController = { }, postCheckout:function(req, res, next) { - Rental.newRental (req.params.title, req.params.customer_id, function(error) { + console.log(req.body) + Rental.newRental (req.params.title, req.body.customer_id, function(error, movie) { if (error) { var err = new Error("Can't rent out"); err.status = 404; diff --git a/models/rental.js b/models/rental.js index 665cccd6b..fc265f543 100644 --- a/models/rental.js +++ b/models/rental.js @@ -28,7 +28,7 @@ Rental.find = function (title, callback) { callback(new Error("Could not retrieve movies"), undefined) } else { callback(null, movies.map (function (movie) { - return new Movie(movie) + return new Movie(movie) })) } }) @@ -75,8 +75,17 @@ Rental.find_customers = function (title, callback) { } Rental.newRental = function (title, cust_id, callback) { - Rental.find(title, function(error, movie) { - db.rentals.saveSync({customer_id: cust_id, movie_id: movie.id, status: true, checkout_date: (new Date()).toString()}) + + db.movies.search({columns:["title"], term: title}, function (error, movies) { + db.rentals.saveSync({customer_id: cust_id, movie_id: movies.id, status: true, checkout_date: (new Date()).toString()}) + if (error || !movies) { + callback(new Error("Could not retrieve movie"), undefined) + } else { + callback(null, movies.map (function (movie) { + console.log(movie) + return new Movie(movie) + })) + } }) } From 7c5938566bafd9db859ee4d09a2c4e933c517f29 Mon Sep 17 00:00:00 2001 From: Jessica Date: Wed, 22 Jun 2016 13:57:03 -0700 Subject: [PATCH 65/93] Rental method for chekcout now successfully reducing inventory --- controllers/rentals.js | 1 - models/rental.js | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index d4089d205..d990557aa 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -42,7 +42,6 @@ RentalsController = { }, postCheckout:function(req, res, next) { - console.log(req.body) Rental.newRental (req.params.title, req.body.customer_id, function(error, movie) { if (error) { var err = new Error("Can't rent out"); diff --git a/models/rental.js b/models/rental.js index fc265f543..db45facd6 100644 --- a/models/rental.js +++ b/models/rental.js @@ -75,14 +75,14 @@ Rental.find_customers = function (title, callback) { } Rental.newRental = function (title, cust_id, callback) { - db.movies.search({columns:["title"], term: title}, function (error, movies) { db.rentals.saveSync({customer_id: cust_id, movie_id: movies.id, status: true, checkout_date: (new Date()).toString()}) + var movieInventory = movies[0].inventory - 1 + db.movies.updateSync({id: movies[0].id, inventory: movieInventory}) if (error || !movies) { callback(new Error("Could not retrieve movie"), undefined) } else { callback(null, movies.map (function (movie) { - console.log(movie) return new Movie(movie) })) } From 5584486d70c49f08d9552b03bc7dc3041c942777 Mon Sep 17 00:00:00 2001 From: Jessica Date: Wed, 22 Jun 2016 14:08:50 -0700 Subject: [PATCH 66/93] return date calculates and saves to rental database --- models/rental.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/models/rental.js b/models/rental.js index db45facd6..6d3510f27 100644 --- a/models/rental.js +++ b/models/rental.js @@ -76,9 +76,12 @@ Rental.find_customers = function (title, callback) { Rental.newRental = function (title, cust_id, callback) { db.movies.search({columns:["title"], term: title}, function (error, movies) { - db.rentals.saveSync({customer_id: cust_id, movie_id: movies.id, status: true, checkout_date: (new Date()).toString()}) - var movieInventory = movies[0].inventory - 1 - db.movies.updateSync({id: movies[0].id, inventory: movieInventory}) + var today = new Date() + var next_week = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000) + console.log(next_week) + db.rentals.saveSync({customer_id: cust_id, movie_id: movies.id, status: true, checkout_date: (new Date()).toString(), return_date: next_week.toString()}) + var movieInventory = movies[0].inventory - 1 + db.movies.updateSync({id: movies[0].id, inventory: movieInventory}) if (error || !movies) { callback(new Error("Could not retrieve movie"), undefined) } else { From 52fcae5c21ef2831999a722ecfc1dc35b142fae3 Mon Sep 17 00:00:00 2001 From: Jessica Date: Thu, 23 Jun 2016 11:17:32 -0700 Subject: [PATCH 67/93] extracting logic from rental checkout method for reusability. added logic to not allow customer to checkout when inventory is 0 but not sure if working yet. --- models/rental.js | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/models/rental.js b/models/rental.js index 6d3510f27..62ebce03b 100644 --- a/models/rental.js +++ b/models/rental.js @@ -66,7 +66,7 @@ Rental.findHistoryMovies = function (title, callback) { }) } -Rental.find_customers = function (title, callback) { +Rental.findCustomers = function (title, callback) { db.find_current_rentals([title], function (error, customers) { callback(null, customers.map(function (customer) { return new Customer(customer) @@ -76,21 +76,32 @@ Rental.find_customers = function (title, callback) { Rental.newRental = function (title, cust_id, callback) { db.movies.search({columns:["title"], term: title}, function (error, movies) { - var today = new Date() - var next_week = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000) - console.log(next_week) - db.rentals.saveSync({customer_id: cust_id, movie_id: movies.id, status: true, checkout_date: (new Date()).toString(), return_date: next_week.toString()}) - var movieInventory = movies[0].inventory - 1 - db.movies.updateSync({id: movies[0].id, inventory: movieInventory}) - if (error || !movies) { - callback(new Error("Could not retrieve movie"), undefined) + if (movies[0].inventory <= 0) { + return "No copies available for checkout" } else { - callback(null, movies.map (function (movie) { - return new Movie(movie) - })) + var today = new Date() + var returnDate = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000) + db.rentals.saveSync({customer_id: cust_id, movie_id: movies.id, status: true, checkout_date: (new Date()).toString(), return_date: returnDate.toString()}) + db.movies.updateSync({id: movies[0].id, inventory: Rental.removeInventory(movies)}) + console.log(movies[0].inventory, movies[0].return_date) + if (error || !movies) { + callback(new Error("Could not retrieve movie"), undefined) + } else { + callback(null, movies.map (function (movie) { + return new Movie(movie) + })) + } } }) } +Rental.removeInventory = function (movie) { + return movie[0].inventory - 1 +} + +Rental.addInventory = function (movie) { + return movie[0].inventory + 1 +} + module.exports = Rental From 3a5c9f342b2a16c09fbaab65292f51c91b1cd8d9 Mon Sep 17 00:00:00 2001 From: Jessica Date: Thu, 23 Jun 2016 11:21:13 -0700 Subject: [PATCH 68/93] added router for rental checkin, plus controller method and model method to start working with. --- controllers/rentals.js | 17 +++++++++++++++-- models/rental.js | 14 +++++++++++++- routes/rentals.js | 2 ++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index d990557aa..c1a24eb1b 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -42,16 +42,29 @@ RentalsController = { }, postCheckout:function(req, res, next) { - Rental.newRental (req.params.title, req.body.customer_id, function(error, movie) { + Rental.checkout (req.params.title, req.body.customer_id, function(error, movie) { if (error) { var err = new Error("Can't rent out"); err.status = 404; next(err); } else { - res.json({checkout: "Success, you checked out, you fancy."}) + res.json({checkout: "Success, you checked out, you fancy!"}) + } + }) + }, + + postCheckin:function(req, res, next) { + Rental.checkin (req.params.title, req.body.customer_id, function(error, movie) { + if (error) { + var err = new Error("Can't rent out"); + err.status = 404; + next(err); + } else { + res.json({checkin: "Success, you checked in that movie!"}) } }) } + } module.exports = RentalsController diff --git a/models/rental.js b/models/rental.js index 62ebce03b..aa279e630 100644 --- a/models/rental.js +++ b/models/rental.js @@ -74,7 +74,7 @@ Rental.findCustomers = function (title, callback) { }) } -Rental.newRental = function (title, cust_id, callback) { +Rental.checkout = function (title, cust_id, callback) { db.movies.search({columns:["title"], term: title}, function (error, movies) { if (movies[0].inventory <= 0) { return "No copies available for checkout" @@ -95,6 +95,18 @@ Rental.newRental = function (title, cust_id, callback) { }) } +Rental.checkin = function (title, cust_id, callback) { + db.movies.search({columns:["title"], term: title}, function (error, movies) { + if (error || !movies) { + callback(new Error("Could not retrieve movie"), undefined) + } else { + callback(null, movies.map (function (movie) { + return new Movie(movie) + })) + } + }) +} + Rental.removeInventory = function (movie) { return movie[0].inventory - 1 } diff --git a/routes/rentals.js b/routes/rentals.js index cf07a517f..ff50e9fd5 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -7,5 +7,7 @@ router.get('/:title', Controller.getRentalsShow) router.get('/:title/customers', Controller.getRentalsCustomers) router.post('/:title/checkout', Controller.postCheckout) +router.post('/:title/checkin', Controller.postCheckin) + module.exports = router From f035554dd2fa31cb73c1880f01376cfb1b2f8cc1 Mon Sep 17 00:00:00 2001 From: Jessica Date: Thu, 23 Jun 2016 13:16:10 -0700 Subject: [PATCH 69/93] got error handling working for when inventory is less than 1 --- controllers/rentals.js | 3 ++- models/rental.js | 19 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index c1a24eb1b..400e9e340 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -46,7 +46,8 @@ RentalsController = { if (error) { var err = new Error("Can't rent out"); err.status = 404; - next(err); + next(error); + res.json({}) } else { res.json({checkout: "Success, you checked out, you fancy!"}) } diff --git a/models/rental.js b/models/rental.js index aa279e630..e1c1fb0d2 100644 --- a/models/rental.js +++ b/models/rental.js @@ -76,25 +76,24 @@ Rental.findCustomers = function (title, callback) { Rental.checkout = function (title, cust_id, callback) { db.movies.search({columns:["title"], term: title}, function (error, movies) { - if (movies[0].inventory <= 0) { - return "No copies available for checkout" + if (error || !movies) { + callback(error) + } else if (error || movies[0].inventory < 1) { + console.log(movies[0].inventory) + callback(error || new Error("No more copies available"), undefined) } else { var today = new Date() var returnDate = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000) db.rentals.saveSync({customer_id: cust_id, movie_id: movies.id, status: true, checkout_date: (new Date()).toString(), return_date: returnDate.toString()}) db.movies.updateSync({id: movies[0].id, inventory: Rental.removeInventory(movies)}) - console.log(movies[0].inventory, movies[0].return_date) - if (error || !movies) { - callback(new Error("Could not retrieve movie"), undefined) - } else { - callback(null, movies.map (function (movie) { - return new Movie(movie) - })) - } + callback(null, movies.map (function (movie) { + return new Movie(movie) + })) } }) } + Rental.checkin = function (title, cust_id, callback) { db.movies.search({columns:["title"], term: title}, function (error, movies) { if (error || !movies) { From 2678ec45751d57867bd179a5450783e9b81f5a98 Mon Sep 17 00:00:00 2001 From: Adriana Date: Thu, 23 Jun 2016 14:26:40 -0700 Subject: [PATCH 70/93] Added a find by id method --- models/customer.js | 10 ++++++++++ models/rental.js | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/models/customer.js b/models/customer.js index 4977b7599..dee957319 100644 --- a/models/customer.js +++ b/models/customer.js @@ -31,6 +31,16 @@ Customer.find = function(name, callback) { }) } +Customer.find_by_id = function(id, callback) { + db.customers.findOne({id: id}, function(error, customer) { + if(error || !customer) { + callback(new Error("Customer not found"), undefined) + } else { + callback(null, new Customer(customer)) + } + }) +} + Customer.sort = function(field, n, p, callback){ db.customers.find({}, { order: field, diff --git a/models/rental.js b/models/rental.js index e1c1fb0d2..a4d2ed2ea 100644 --- a/models/rental.js +++ b/models/rental.js @@ -79,13 +79,13 @@ Rental.checkout = function (title, cust_id, callback) { if (error || !movies) { callback(error) } else if (error || movies[0].inventory < 1) { - console.log(movies[0].inventory) callback(error || new Error("No more copies available"), undefined) } else { var today = new Date() var returnDate = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000) db.rentals.saveSync({customer_id: cust_id, movie_id: movies.id, status: true, checkout_date: (new Date()).toString(), return_date: returnDate.toString()}) db.movies.updateSync({id: movies[0].id, inventory: Rental.removeInventory(movies)}) + callback(null, movies.map (function (movie) { return new Movie(movie) })) @@ -114,5 +114,9 @@ Rental.addInventory = function (movie) { return movie[0].inventory + 1 } +// Rental.charge = function (customer) { +// // console.log(customer); +// return customer.account_credit - 1 +// } module.exports = Rental From a189ac7306209d65ac3d5ab3773c3416f2e05672 Mon Sep 17 00:00:00 2001 From: Adriana Date: Thu, 23 Jun 2016 14:39:57 -0700 Subject: [PATCH 71/93] Added function to charge a customer 1.00 to rent out. Went into the database and changed the charge amount --- models/rental.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/models/rental.js b/models/rental.js index a4d2ed2ea..3d042bd0e 100644 --- a/models/rental.js +++ b/models/rental.js @@ -86,6 +86,10 @@ Rental.checkout = function (title, cust_id, callback) { db.rentals.saveSync({customer_id: cust_id, movie_id: movies.id, status: true, checkout_date: (new Date()).toString(), return_date: returnDate.toString()}) db.movies.updateSync({id: movies[0].id, inventory: Rental.removeInventory(movies)}) + Customer.find_by_id(cust_id, function (error, customer) { + db.customers.updateSync({id: cust_id, account_credit: Rental.charge(customer)}) + }) + callback(null, movies.map (function (movie) { return new Movie(movie) })) @@ -114,9 +118,8 @@ Rental.addInventory = function (movie) { return movie[0].inventory + 1 } -// Rental.charge = function (customer) { -// // console.log(customer); -// return customer.account_credit - 1 -// } +Rental.charge = function (customer) { + return customer.account_credit - 1.00 +} module.exports = Rental From 2fc868d52d2f890085d069dbcbc0dc0a3145ad2e Mon Sep 17 00:00:00 2001 From: Adriana Date: Thu, 23 Jun 2016 14:47:44 -0700 Subject: [PATCH 72/93] Made put routes, and renamed functions as put --- controllers/rentals.js | 6 +++--- models/rental.js | 2 -- routes/rentals.js | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index 400e9e340..2772b8333 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -54,14 +54,14 @@ RentalsController = { }) }, - postCheckin:function(req, res, next) { + putCheckin:function(req, res, next) { Rental.checkin (req.params.title, req.body.customer_id, function(error, movie) { if (error) { - var err = new Error("Can't rent out"); + var err = new Error("Can't return, try again later"); err.status = 404; next(err); } else { - res.json({checkin: "Success, you checked in that movie!"}) + res.json({checkin: "Success, you checked that movie in, yo!"}) } }) } diff --git a/models/rental.js b/models/rental.js index 3d042bd0e..6d4b37933 100644 --- a/models/rental.js +++ b/models/rental.js @@ -85,11 +85,9 @@ Rental.checkout = function (title, cust_id, callback) { var returnDate = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000) db.rentals.saveSync({customer_id: cust_id, movie_id: movies.id, status: true, checkout_date: (new Date()).toString(), return_date: returnDate.toString()}) db.movies.updateSync({id: movies[0].id, inventory: Rental.removeInventory(movies)}) - Customer.find_by_id(cust_id, function (error, customer) { db.customers.updateSync({id: cust_id, account_credit: Rental.charge(customer)}) }) - callback(null, movies.map (function (movie) { return new Movie(movie) })) diff --git a/routes/rentals.js b/routes/rentals.js index ff50e9fd5..227ebc44d 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -7,7 +7,7 @@ router.get('/:title', Controller.getRentalsShow) router.get('/:title/customers', Controller.getRentalsCustomers) router.post('/:title/checkout', Controller.postCheckout) -router.post('/:title/checkin', Controller.postCheckin) +router.put('/:title/checkin', Controller.putCheckin) module.exports = router From 935a54c1ba97b6199fb0653e969d6d5b14dcf686 Mon Sep 17 00:00:00 2001 From: Adriana Date: Thu, 23 Jun 2016 16:21:15 -0700 Subject: [PATCH 73/93] Changed rental database to false and added to movie inventory when rental was returned --- models/rental.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/models/rental.js b/models/rental.js index 6d4b37933..0e7ae21ce 100644 --- a/models/rental.js +++ b/models/rental.js @@ -83,7 +83,7 @@ Rental.checkout = function (title, cust_id, callback) { } else { var today = new Date() var returnDate = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000) - db.rentals.saveSync({customer_id: cust_id, movie_id: movies.id, status: true, checkout_date: (new Date()).toString(), return_date: returnDate.toString()}) + db.rentals.saveSync({customer_id: cust_id, movie_id: movies[0].id, status: true, checkout_date: (new Date()).toString(), return_date: returnDate.toString()}) db.movies.updateSync({id: movies[0].id, inventory: Rental.removeInventory(movies)}) Customer.find_by_id(cust_id, function (error, customer) { db.customers.updateSync({id: cust_id, account_credit: Rental.charge(customer)}) @@ -98,6 +98,10 @@ Rental.checkout = function (title, cust_id, callback) { Rental.checkin = function (title, cust_id, callback) { db.movies.search({columns:["title"], term: title}, function (error, movies) { + db.rentals.find({movie_id: movies[0].id, customer_id: cust_id}, function (error, rental) { + db.rentals.updateSync({id: rental[0].id, status: false}) + db.movies.updateSync({id: movies[0].id, inventory: Rental.addInventory(movies)}) + }) if (error || !movies) { callback(new Error("Could not retrieve movie"), undefined) } else { From d5d4db663371cd72f2c84c3f83b41123a511d1a5 Mon Sep 17 00:00:00 2001 From: Adriana Date: Thu, 23 Jun 2016 16:42:39 -0700 Subject: [PATCH 74/93] Added ; in sql query, renamed so functions matched --- db/find_current_rentals.sql | 2 +- models/rental.js | 2 +- routes/rentals.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/db/find_current_rentals.sql b/db/find_current_rentals.sql index 96928fe65..1e9e5fbdc 100644 --- a/db/find_current_rentals.sql +++ b/db/find_current_rentals.sql @@ -5,4 +5,4 @@ INNER JOIN movies ON movies.id=rentals.movie_id INNER JOIN customers ON rentals.customer_id=customers.id -WHERE movies.title=$1 AND rentals.status=true +WHERE movies.title=$1 AND rentals.status=true; diff --git a/models/rental.js b/models/rental.js index 0e7ae21ce..f6fe8c614 100644 --- a/models/rental.js +++ b/models/rental.js @@ -66,7 +66,7 @@ Rental.findHistoryMovies = function (title, callback) { }) } -Rental.findCustomers = function (title, callback) { +Rental.find_customers = function (title, callback) { db.find_current_rentals([title], function (error, customers) { callback(null, customers.map(function (customer) { return new Customer(customer) diff --git a/routes/rentals.js b/routes/rentals.js index 227ebc44d..3f79157ba 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -6,8 +6,8 @@ router.get('/', Controller.getRentals) router.get('/:title', Controller.getRentalsShow) router.get('/:title/customers', Controller.getRentalsCustomers) + router.post('/:title/checkout', Controller.postCheckout) router.put('/:title/checkin', Controller.putCheckin) - module.exports = router From 075bed0ba937da847ad69bcaab0d662ad335b3ba Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 24 Jun 2016 09:14:08 -0700 Subject: [PATCH 75/93] made routes and started method for overdue --- controllers/rentals.js | 13 ++++++++++++- models/rental.js | 8 ++++++++ routes/rentals.js | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index 2772b8333..f06c88365 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -64,8 +64,19 @@ RentalsController = { res.json({checkin: "Success, you checked that movie in, yo!"}) } }) - } + }, + overdue:function(req, res, next) { + Rental.overdueRental (function(error, rental) { + if (error) { + var err = new Error("Did not work :( "); + err.status = 404; + next(err); + } else { + res.json(rental) + } + }) + } } module.exports = RentalsController diff --git a/models/rental.js b/models/rental.js index f6fe8c614..172836c78 100644 --- a/models/rental.js +++ b/models/rental.js @@ -111,6 +111,14 @@ Rental.checkin = function (title, cust_id, callback) { } }) } +// var myString = "12/20/2012-12/24/2012", +// parts = myString.split("-"); +// if (Date.parse(parts[0]) < Date.now()) { +// alert("start date has past the present date"); +// } +Rental.overdueRental = function (callback) { + db.rentals.where("status=true && return_date") +} Rental.removeInventory = function (movie) { return movie[0].inventory - 1 diff --git a/routes/rentals.js b/routes/rentals.js index 3f79157ba..9d6c49d33 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -5,7 +5,7 @@ var Controller = require('../controllers/rentals') router.get('/', Controller.getRentals) router.get('/:title', Controller.getRentalsShow) router.get('/:title/customers', Controller.getRentalsCustomers) - +router.get('/overdue', Controller.overdue) router.post('/:title/checkout', Controller.postCheckout) router.put('/:title/checkin', Controller.putCheckin) From f6698f60ef5db9311384b73c78a143b66bfb9069 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 24 Jun 2016 10:28:24 -0700 Subject: [PATCH 76/93] overdue rentals model working to return rentals, working on getting it to return customers --- controllers/rentals.js | 7 +++---- db/seeds/rentals.json | 2 +- models/rental.js | 20 +++++++++++++------- routes/rentals.js | 2 +- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/controllers/rentals.js b/controllers/rentals.js index f06c88365..81e077cd3 100644 --- a/controllers/rentals.js +++ b/controllers/rentals.js @@ -54,7 +54,7 @@ RentalsController = { }) }, - putCheckin:function(req, res, next) { + putCheckin: function(req, res, next) { Rental.checkin (req.params.title, req.body.customer_id, function(error, movie) { if (error) { var err = new Error("Can't return, try again later"); @@ -66,12 +66,11 @@ RentalsController = { }) }, - overdue:function(req, res, next) { - Rental.overdueRental (function(error, rental) { + overdue: function (req, res) { + Rental.overdueRental (function (error, rental) { if (error) { var err = new Error("Did not work :( "); err.status = 404; - next(err); } else { res.json(rental) } diff --git a/db/seeds/rentals.json b/db/seeds/rentals.json index c021ca52d..ce3b68501 100644 --- a/db/seeds/rentals.json +++ b/db/seeds/rentals.json @@ -9,7 +9,7 @@ "customer_id": 19, "movie_id": 69, "status": true, -"return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" +"return_date": "Sun Jun 10 2016 22:19:53 GMT-0700 (PDT)" }, { "customer_id": 19, diff --git a/models/rental.js b/models/rental.js index 172836c78..96f5eeba4 100644 --- a/models/rental.js +++ b/models/rental.js @@ -111,14 +111,20 @@ Rental.checkin = function (title, cust_id, callback) { } }) } -// var myString = "12/20/2012-12/24/2012", -// parts = myString.split("-"); -// if (Date.parse(parts[0]) < Date.now()) { -// alert("start date has past the present date"); -// } + Rental.overdueRental = function (callback) { - db.rentals.where("status=true && return_date") -} + db.rentals.find({ status: true }, function (error, rentals) { + callback(null, rentals.map (function (rental) { + var today = new Date() + var returnDate = rental.return_date + if (Date.parse(returnDate) < today) { + db.customers.find({id: rental.customer_id, function (err, customer) { + return new Customer(customer) + } + }) + })) + // }) +}) Rental.removeInventory = function (movie) { return movie[0].inventory - 1 diff --git a/routes/rentals.js b/routes/rentals.js index 9d6c49d33..50039a21d 100644 --- a/routes/rentals.js +++ b/routes/rentals.js @@ -3,9 +3,9 @@ var router = express.Router() var Controller = require('../controllers/rentals') router.get('/', Controller.getRentals) +router.get('/overdue', Controller.overdue) router.get('/:title', Controller.getRentalsShow) router.get('/:title/customers', Controller.getRentalsCustomers) -router.get('/overdue', Controller.overdue) router.post('/:title/checkout', Controller.postCheckout) router.put('/:title/checkin', Controller.putCheckin) From 2e0369e2014ac51ab5fcc6264aefc6a1dbfccb90 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 24 Jun 2016 10:31:52 -0700 Subject: [PATCH 77/93] Found a missing token --- models/rental.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/models/rental.js b/models/rental.js index 96f5eeba4..fff27aa58 100644 --- a/models/rental.js +++ b/models/rental.js @@ -113,18 +113,18 @@ Rental.checkin = function (title, cust_id, callback) { } Rental.overdueRental = function (callback) { - db.rentals.find({ status: true }, function (error, rentals) { + db.rentals.find({ status: true }, function (error, rentals) { callback(null, rentals.map (function (rental) { var today = new Date() var returnDate = rental.return_date if (Date.parse(returnDate) < today) { - db.customers.find({id: rental.customer_id, function (err, customer) { - return new Customer(customer) + db.customers.find({id: rental.customer_id}, function (err, customer) { + return new Customer(customer) + }) } - }) })) - // }) -}) + }) +} Rental.removeInventory = function (movie) { return movie[0].inventory - 1 From c1662245a76348780164b9c5af4a1a7745537ed1 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 24 Jun 2016 10:39:46 -0700 Subject: [PATCH 78/93] Added a sql file to join customers and rentals --- db/overdue_rentals.sql | 6 ++++++ models/rental.js | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 db/overdue_rentals.sql diff --git a/db/overdue_rentals.sql b/db/overdue_rentals.sql new file mode 100644 index 000000000..d66812b88 --- /dev/null +++ b/db/overdue_rentals.sql @@ -0,0 +1,6 @@ + +SELECT rentals.status, rentals.customer_id, customers.* +FROM rentals +INNER JOIN customers +ON customers.id=rentals.customer_id +WHERE rentals.status=true; diff --git a/models/rental.js b/models/rental.js index fff27aa58..4c730053f 100644 --- a/models/rental.js +++ b/models/rental.js @@ -119,9 +119,10 @@ Rental.overdueRental = function (callback) { var returnDate = rental.return_date if (Date.parse(returnDate) < today) { db.customers.find({id: rental.customer_id}, function (err, customer) { - return new Customer(customer) + console.log(customer[0]); }) } + return new Customer(customer) })) }) } From 2366743e79f1cec8dbbbec9cd2a970242a96dca1 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 24 Jun 2016 10:44:40 -0700 Subject: [PATCH 79/93] Sql file is working, yay --- models/rental.js | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/models/rental.js b/models/rental.js index 4c730053f..118556fe0 100644 --- a/models/rental.js +++ b/models/rental.js @@ -113,18 +113,23 @@ Rental.checkin = function (title, cust_id, callback) { } Rental.overdueRental = function (callback) { - db.rentals.find({ status: true }, function (error, rentals) { - callback(null, rentals.map (function (rental) { - var today = new Date() - var returnDate = rental.return_date - if (Date.parse(returnDate) < today) { - db.customers.find({id: rental.customer_id}, function (err, customer) { - console.log(customer[0]); - }) - } + db.overdue_rentals(function (error, customers) { + callback(null, customers.map (function (customer) { return new Customer(customer) })) }) + // db.rentals.find({ status: true }, function (error, rentals) { + // callback(null, rentals.map (function (rental) { + // var today = new Date() + // var returnDate = rental.return_date + // if (Date.parse(returnDate) < today) { + // db.customers.find({id: rental.customer_id}, function (err, customer) { + // console.log(customer[0]); + // }) + // } + // return new Customer(customer) + // })) + // }) } Rental.removeInventory = function (movie) { From e6a0e2e7757851d00278d8ecef212dfa56966ad8 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 24 Jun 2016 11:00:43 -0700 Subject: [PATCH 80/93] Finished function to return customers that have late data --- db/overdue_rentals.sql | 4 ++-- models/rental.js | 12 ------------ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/db/overdue_rentals.sql b/db/overdue_rentals.sql index d66812b88..1547cf96a 100644 --- a/db/overdue_rentals.sql +++ b/db/overdue_rentals.sql @@ -1,6 +1,6 @@ -SELECT rentals.status, rentals.customer_id, customers.* +SELECT rentals.status, rentals.customer_id, rentals.return_date, customers.* FROM rentals INNER JOIN customers ON customers.id=rentals.customer_id -WHERE rentals.status=true; +WHERE rentals.status=true AND to_date(return_date, 'Dy Mon DD YYYY') Date: Fri, 24 Jun 2016 13:34:36 -0700 Subject: [PATCH 81/93] updating --- controllers/customers.js | 5 +++-- db/customer_rental_history.sql | 9 +++++++++ db/seeds/rentals.json | 9 +++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/controllers/customers.js b/controllers/customers.js index ffda84d1d..2d454e068 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -55,13 +55,14 @@ CustomersController = { }, getRentalsHistory: function (req, res, next) { - Rental.findHistory(req.params.id, function (error, rental) { + Rental.findHistory(req.params.id, function (error, movie) { if (error) { var err = new Error("Error retrieving rental history:\n" + error.message); err.status = 500; next(err); } else { - res.json(rental) + console.log(movie); + res.json(movie) } }) } diff --git a/db/customer_rental_history.sql b/db/customer_rental_history.sql index 77b2fcac8..55509364b 100644 --- a/db/customer_rental_history.sql +++ b/db/customer_rental_history.sql @@ -7,3 +7,12 @@ INNER JOIN customers ON rentals.customer_id=customers.id WHERE movies.title=$1 AND rentals.status=false ORDER BY customers.name; + +-- SELECT rentals.movie_id, rentals.customer_id, rentals.status, rentals.checkout_date, customers.*, movies.* +-- FROM rentals +-- INNER JOIN movies +-- ON movies.id=rentals.movie_id +-- INNER JOIN customers +-- ON rentals.customer_id=customers.id +-- WHERE movies.title=$1 AND rentals.status=false +-- ORDER BY to_date(rentals.checkout_date, 'Dy Mon DD YYYY'); diff --git a/db/seeds/rentals.json b/db/seeds/rentals.json index ce3b68501..7ab6407f7 100644 --- a/db/seeds/rentals.json +++ b/db/seeds/rentals.json @@ -3,54 +3,63 @@ "customer_id": 1, "movie_id": 29, "status": true, +"checkout_date": "Fri Jun 10 2016 20:19:53 GMT-0700 (PDT)", "return_date": "Sun Jun 19 2016 22:19:53 GMT-0700 (PDT)" }, { "customer_id": 19, "movie_id": 69, "status": true, +"checkout_date": "Fri Jun 17 2016 20:19:53 GMT-0700 (PDT)", "return_date": "Sun Jun 10 2016 22:19:53 GMT-0700 (PDT)" }, { "customer_id": 19, "movie_id": 39, "status": true, +"checkout_date": "Fri Jun 24 2016 20:19:53 GMT-0700 (PDT)", "return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" }, { "customer_id": 29, "movie_id": 39, "status": true, +"checkout_date": "Fri Jun 10 2016 20:19:53 GMT-0700 (PDT)", "return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" }, { "customer_id": 29, "movie_id": 19, "status": true, +"checkout_date": "Fri Jun 24 2016 20:19:53 GMT-0700 (PDT)", "return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" }, { "customer_id": 29, "movie_id": 99, "status": true, +"checkout_date": "Fri Jun 17 2016 20:19:53 GMT-0700 (PDT)", "return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" }, { "customer_id": 28, "movie_id": 89, "status": false, +"checkout_date": "Fri Jun 17 2016 20:19:53 GMT-0700 (PDT)", "return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" }, { "customer_id": 27, "movie_id": 89, "status": true, +"checkout_date": "Fri Jun 17 2016 20:19:53 GMT-0700 (PDT)", "return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" }, { "customer_id": 29, "movie_id": 89, "status": false, +"checkout_date": "Fri Jun 17 2016 20:19:53 GMT-0700 (PDT)", "return_date": "Sun Jul 10 2016 22:19:53 GMT-0700 (PDT)" } ] From 9cd7d072df9163a56ab690aca36eb02135af9728 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 24 Jun 2016 13:35:18 -0700 Subject: [PATCH 82/93] merging --- controllers/customers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/controllers/customers.js b/controllers/customers.js index ffda84d1d..99b746c3b 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -56,6 +56,7 @@ CustomersController = { getRentalsHistory: function (req, res, next) { Rental.findHistory(req.params.id, function (error, rental) { + console.log(rental) if (error) { var err = new Error("Error retrieving rental history:\n" + error.message); err.status = 500; From 2e9702598fb8f6dd7e4c9d8243c4830ba14df5f5 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 24 Jun 2016 13:53:05 -0700 Subject: [PATCH 83/93] fixed customer rental history to order by checkout and show movies --- controllers/customers.js | 3 +-- db/history.sql | 8 ++++++++ models/rental.js | 7 ++++--- 3 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 db/history.sql diff --git a/controllers/customers.js b/controllers/customers.js index 7c9a179e3..e077f1cfc 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -55,13 +55,12 @@ CustomersController = { }, getRentalsHistory: function (req, res, next) { - Rental.findHistory(req.params.id, function (error, rental) { + Rental.findHistory(req.params.id, function (error, movie) { if (error) { var err = new Error("Error retrieving rental history:\n" + error.message); err.status = 500; next(err); } else { - console.log(movie); res.json(movie) } }) diff --git a/db/history.sql b/db/history.sql new file mode 100644 index 000000000..9c4f8671d --- /dev/null +++ b/db/history.sql @@ -0,0 +1,8 @@ +SELECT rentals.movie_id, rentals.customer_id, customers.id, movies.* +FROM rentals +INNER JOIN customers +ON rentals.customer_id=customers.id +INNER JOIN movies +ON movies.id=rentals.movie_id +WHERE rentals.customer_id=$1 +ORDER BY to_date(rentals.checkout_date, 'Dy Mon DD YYYY'); diff --git a/models/rental.js b/models/rental.js index 3874e2c44..141932a82 100644 --- a/models/rental.js +++ b/models/rental.js @@ -43,9 +43,10 @@ Rental.findCurrent = function (id, callback) { } Rental.findHistory = function (id, callback) { - db.rentals.find({customer_id: id}, function (error, rentals) { - callback(null, rentals.map (function (rental) { - return new Rental(rental) + db.history([id], function (error, movies) { + console.log(movies) + callback(null, movies.map (function (movie) { + return new Movie(movie) })) }) } From 50740f6a35b497e14c069b39a7d361303d058f0d Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 24 Jun 2016 13:57:14 -0700 Subject: [PATCH 84/93] fixed current rentals by customer to show movies --- controllers/customers.js | 4 ++-- db/current.sql | 7 +++++++ models/rental.js | 6 +++--- 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 db/current.sql diff --git a/controllers/customers.js b/controllers/customers.js index e077f1cfc..f3d3e83b6 100644 --- a/controllers/customers.js +++ b/controllers/customers.js @@ -43,13 +43,13 @@ CustomersController = { }, getRentalsCurrent: function (req, res, next) { - Rental.findCurrent(req.params.id, function (error, rental) { + Rental.findCurrent(req.params.id, function (error, movie) { if (error) { var err = new Error("Error retrieving current rentals:\n" + error.message); err.status = 500; next(err); } else { - res.json(rental) + res.json(movie) } }) }, diff --git a/db/current.sql b/db/current.sql new file mode 100644 index 000000000..b7dc47bce --- /dev/null +++ b/db/current.sql @@ -0,0 +1,7 @@ +SELECT rentals.movie_id, rentals.customer_id, customers.id, movies.* +FROM rentals +INNER JOIN customers +ON rentals.customer_id=customers.id +INNER JOIN movies +ON movies.id=rentals.movie_id +WHERE rentals.customer_id=$1 AND rentals.status=true; diff --git a/models/rental.js b/models/rental.js index 141932a82..cb7706ee9 100644 --- a/models/rental.js +++ b/models/rental.js @@ -35,9 +35,9 @@ Rental.find = function (title, callback) { } Rental.findCurrent = function (id, callback) { - db.rentals.find({customer_id: id, status: true}, function (error, rentals) { - callback(null, rentals.map (function (rental) { - return new Rental(rental) + db.current([id], function (error, movies) { + callback(null, movies.map (function (movie) { + return new Movie(movie) })) }) } From 417de7e419df673895f2baf707bac743ae36633a Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 24 Jun 2016 14:02:17 -0700 Subject: [PATCH 85/93] fixing sql for movie rental history showing customers --- db/customer_rental_history.sql | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/db/customer_rental_history.sql b/db/customer_rental_history.sql index 55509364b..bd77a561c 100644 --- a/db/customer_rental_history.sql +++ b/db/customer_rental_history.sql @@ -1,18 +1,8 @@ - SELECT movies.id, rentals.movie_id, rentals.customer_id, rentals.status, customers.* FROM rentals INNER JOIN movies ON movies.id=rentals.movie_id INNER JOIN customers ON rentals.customer_id=customers.id -WHERE movies.title=$1 AND rentals.status=false +WHERE movies.title=$1 ORDER BY customers.name; - --- SELECT rentals.movie_id, rentals.customer_id, rentals.status, rentals.checkout_date, customers.*, movies.* --- FROM rentals --- INNER JOIN movies --- ON movies.id=rentals.movie_id --- INNER JOIN customers --- ON rentals.customer_id=customers.id --- WHERE movies.title=$1 AND rentals.status=false --- ORDER BY to_date(rentals.checkout_date, 'Dy Mon DD YYYY'); From 4092545e9fee1c4b22fa9e3d9a0431b23c19ea05 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 24 Jun 2016 14:18:49 -0700 Subject: [PATCH 86/93] fixed overdue rentals to show info for customer and movies --- db/overdue_rentals.sql | 5 +++-- models/rental.js | 5 +++-- npm-debug.log | 49 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 npm-debug.log diff --git a/db/overdue_rentals.sql b/db/overdue_rentals.sql index 1547cf96a..0055959f6 100644 --- a/db/overdue_rentals.sql +++ b/db/overdue_rentals.sql @@ -1,6 +1,7 @@ - -SELECT rentals.status, rentals.customer_id, rentals.return_date, customers.* +SELECT rentals.status, rentals.customer_id, rentals.return_date, customers.*, rentals.checkout_date, movies.title FROM rentals +INNER JOIN movies +ON rentals.movie_id=movies.id INNER JOIN customers ON customers.id=rentals.customer_id WHERE rentals.status=true AND to_date(return_date, 'Dy Mon DD YYYY') (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:245:16) +14 verbose stack at emitTwo (events.js:106:13) +14 verbose stack at EventEmitter.emit (events.js:191:7) +14 verbose stack at ChildProcess. (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:24:14) +14 verbose stack at emitTwo (events.js:106:13) +14 verbose stack at ChildProcess.emit (events.js:191:7) +14 verbose stack at maybeClose (internal/child_process.js:852:16) +14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:215:5) +15 verbose pkgid video-store-api@0.0.0 +16 verbose cwd /Users/Jessica/C5/projects/VideoStoreAPI +17 error Darwin 15.5.0 +18 error argv "/usr/local/Cellar/node/6.2.1/bin/node" "/usr/local/bin/npm" "run" "test" +19 error node v6.2.1 +20 error npm v3.9.3 +21 error code ELIFECYCLE +22 error video-store-api@0.0.0 test: `clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/` +22 error Exit status 1 +23 error Failed at the video-store-api@0.0.0 test script 'clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/'. +23 error Make sure you have the latest version of node.js and npm installed. +23 error If you do, this is most likely a problem with the video-store-api package, +23 error not with npm itself. +23 error Tell the author that this fails on your system: +23 error clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/ +23 error You can get information on how to open an issue for this project with: +23 error npm bugs video-store-api +23 error Or if that isn't available, you can get their info via: +23 error npm owner ls video-store-api +23 error There is likely additional logging output above. +24 verbose exit [ 1, true ] From 6e8adf2bf152a2260aab91288ea8edb31114c889 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 24 Jun 2016 14:32:40 -0700 Subject: [PATCH 87/93] fixed tests after changing methods in rental model to use sql --- models/rental.js | 1 - npm-debug.log | 49 -------------------------------------- spec/models/rental.spec.js | 17 ++++++------- 3 files changed, 9 insertions(+), 58 deletions(-) delete mode 100644 npm-debug.log diff --git a/models/rental.js b/models/rental.js index b06aebb4e..1a4174e52 100644 --- a/models/rental.js +++ b/models/rental.js @@ -44,7 +44,6 @@ Rental.findCurrent = function (id, callback) { Rental.findHistory = function (id, callback) { db.history([id], function (error, movies) { - console.log(movies) callback(null, movies.map (function (movie) { return new Movie(movie) })) diff --git a/npm-debug.log b/npm-debug.log deleted file mode 100644 index da6a850de..000000000 --- a/npm-debug.log +++ /dev/null @@ -1,49 +0,0 @@ -0 info it worked if it ends with ok -1 verbose cli [ '/usr/local/Cellar/node/6.2.1/bin/node', -1 verbose cli '/usr/local/bin/npm', -1 verbose cli 'run', -1 verbose cli 'test' ] -2 info using npm@3.9.3 -3 info using node@v6.2.1 -4 verbose run-script [ 'pretest', 'test', 'posttest' ] -5 info lifecycle video-store-api@0.0.0~pretest: video-store-api@0.0.0 -6 silly lifecycle video-store-api@0.0.0~pretest: no script for pretest, continuing -7 info lifecycle video-store-api@0.0.0~test: video-store-api@0.0.0 -8 verbose lifecycle video-store-api@0.0.0~test: unsafe-perm in lifecycle true -9 verbose lifecycle video-store-api@0.0.0~test: PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin:/Users/Jessica/C5/projects/VideoStoreAPI/node_modules/.bin:/usr/local/Cellar/node/6.2.1/bin:/Users/Jessica/.rvm/gems/ruby-2.3.0/bin:/Users/Jessica/.rvm/gems/ruby-2.3.0@global/bin:/Users/Jessica/.rvm/rubies/ruby-2.3.0/bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/Jessica/.rvm/bin:/Users/Jessica/.rvm/bin -10 verbose lifecycle video-store-api@0.0.0~test: CWD: /Users/Jessica/C5/projects/VideoStoreAPI -11 silly lifecycle video-store-api@0.0.0~test: Args: [ '-c', -11 silly lifecycle 'clear; ./node_modules/.bin/istanbul cover -x \'spec/**/*\' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/' ] -12 silly lifecycle video-store-api@0.0.0~test: Returned: code: 1 signal: null -13 info lifecycle video-store-api@0.0.0~test: Failed to exec test script -14 verbose stack Error: video-store-api@0.0.0 test: `clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/` -14 verbose stack Exit status 1 -14 verbose stack at EventEmitter. (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:245:16) -14 verbose stack at emitTwo (events.js:106:13) -14 verbose stack at EventEmitter.emit (events.js:191:7) -14 verbose stack at ChildProcess. (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:24:14) -14 verbose stack at emitTwo (events.js:106:13) -14 verbose stack at ChildProcess.emit (events.js:191:7) -14 verbose stack at maybeClose (internal/child_process.js:852:16) -14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:215:5) -15 verbose pkgid video-store-api@0.0.0 -16 verbose cwd /Users/Jessica/C5/projects/VideoStoreAPI -17 error Darwin 15.5.0 -18 error argv "/usr/local/Cellar/node/6.2.1/bin/node" "/usr/local/bin/npm" "run" "test" -19 error node v6.2.1 -20 error npm v3.9.3 -21 error code ELIFECYCLE -22 error video-store-api@0.0.0 test: `clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/` -22 error Exit status 1 -23 error Failed at the video-store-api@0.0.0 test script 'clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/'. -23 error Make sure you have the latest version of node.js and npm installed. -23 error If you do, this is most likely a problem with the video-store-api package, -23 error not with npm itself. -23 error Tell the author that this fails on your system: -23 error clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/ -23 error You can get information on how to open an issue for this project with: -23 error npm bugs video-store-api -23 error Or if that isn't available, you can get their info via: -23 error npm owner ls video-store-api -23 error There is likely additional logging output above. -24 verbose exit [ 1, true ] diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js index efcc86d75..181495615 100644 --- a/spec/models/rental.spec.js +++ b/spec/models/rental.spec.js @@ -44,11 +44,11 @@ describe('Rental', function () { describe("#findHistory", function () { it("should return history rentals for a customer", function (done) { - Rental.findHistory(1, function (error, customer) { - expect(customer[0].customer_id).toEqual(1) - expect(customer[0].movie_id).toEqual(29) - expect(customer[0].status).toEqual(true) - expect(customer[0].return_date).toEqual('Sun Jun 19 2016 22:19:53 GMT-0700 (PDT)') + Rental.findHistory(1, function (error, movie) { + expect(movie[0].id).toEqual(29) + expect(movie[0].title).toEqual('The Shining') + expect(movie[0].release_date).toEqual('1980-05-22') + expect(movie[0].overview).toEqual('Jack Torrance accepts a caretaker job at the Overlook Hotel, where he, along with his wife Wendy and their son Danny, must live isolated from the rest of the world for the winter. But they aren\'t prepared for the madness that lurks within.') done() }) }) @@ -70,9 +70,10 @@ describe('Rental', function () { describe("#findCurrent", function () { it("should return current rentals for a customer", function (done) { - Rental.findCurrent(29, function (error, customer) { - expect(customer.length).toEqual(3) - expect(customer[0].customer_id).toEqual(29) + Rental.findCurrent(29, function (error, movie) { + console.log(movie) + expect(movie.length).toEqual(3) + expect(movie[0].id).toEqual(19) done() }) }) From bb39da26b75e22ba2ecdeaf8fecc1eff300f6375 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 24 Jun 2016 14:53:23 -0700 Subject: [PATCH 88/93] don't know --- npm-debug.log | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 npm-debug.log diff --git a/npm-debug.log b/npm-debug.log deleted file mode 100644 index da6a850de..000000000 --- a/npm-debug.log +++ /dev/null @@ -1,49 +0,0 @@ -0 info it worked if it ends with ok -1 verbose cli [ '/usr/local/Cellar/node/6.2.1/bin/node', -1 verbose cli '/usr/local/bin/npm', -1 verbose cli 'run', -1 verbose cli 'test' ] -2 info using npm@3.9.3 -3 info using node@v6.2.1 -4 verbose run-script [ 'pretest', 'test', 'posttest' ] -5 info lifecycle video-store-api@0.0.0~pretest: video-store-api@0.0.0 -6 silly lifecycle video-store-api@0.0.0~pretest: no script for pretest, continuing -7 info lifecycle video-store-api@0.0.0~test: video-store-api@0.0.0 -8 verbose lifecycle video-store-api@0.0.0~test: unsafe-perm in lifecycle true -9 verbose lifecycle video-store-api@0.0.0~test: PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin:/Users/Jessica/C5/projects/VideoStoreAPI/node_modules/.bin:/usr/local/Cellar/node/6.2.1/bin:/Users/Jessica/.rvm/gems/ruby-2.3.0/bin:/Users/Jessica/.rvm/gems/ruby-2.3.0@global/bin:/Users/Jessica/.rvm/rubies/ruby-2.3.0/bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/Jessica/.rvm/bin:/Users/Jessica/.rvm/bin -10 verbose lifecycle video-store-api@0.0.0~test: CWD: /Users/Jessica/C5/projects/VideoStoreAPI -11 silly lifecycle video-store-api@0.0.0~test: Args: [ '-c', -11 silly lifecycle 'clear; ./node_modules/.bin/istanbul cover -x \'spec/**/*\' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/' ] -12 silly lifecycle video-store-api@0.0.0~test: Returned: code: 1 signal: null -13 info lifecycle video-store-api@0.0.0~test: Failed to exec test script -14 verbose stack Error: video-store-api@0.0.0 test: `clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/` -14 verbose stack Exit status 1 -14 verbose stack at EventEmitter. (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:245:16) -14 verbose stack at emitTwo (events.js:106:13) -14 verbose stack at EventEmitter.emit (events.js:191:7) -14 verbose stack at ChildProcess. (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:24:14) -14 verbose stack at emitTwo (events.js:106:13) -14 verbose stack at ChildProcess.emit (events.js:191:7) -14 verbose stack at maybeClose (internal/child_process.js:852:16) -14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:215:5) -15 verbose pkgid video-store-api@0.0.0 -16 verbose cwd /Users/Jessica/C5/projects/VideoStoreAPI -17 error Darwin 15.5.0 -18 error argv "/usr/local/Cellar/node/6.2.1/bin/node" "/usr/local/bin/npm" "run" "test" -19 error node v6.2.1 -20 error npm v3.9.3 -21 error code ELIFECYCLE -22 error video-store-api@0.0.0 test: `clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/` -22 error Exit status 1 -23 error Failed at the video-store-api@0.0.0 test script 'clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/'. -23 error Make sure you have the latest version of node.js and npm installed. -23 error If you do, this is most likely a problem with the video-store-api package, -23 error not with npm itself. -23 error Tell the author that this fails on your system: -23 error clear; ./node_modules/.bin/istanbul cover -x 'spec/**/*' -- ./node_modules/.bin/jasmine-node --captureExceptions --verbose spec/ -23 error You can get information on how to open an issue for this project with: -23 error npm bugs video-store-api -23 error Or if that isn't available, you can get their info via: -23 error npm owner ls video-store-api -23 error There is likely additional logging output above. -24 verbose exit [ 1, true ] From 04e06548f8135b35b7b96e19b0caa5f866867101 Mon Sep 17 00:00:00 2001 From: Adriana Date: Fri, 24 Jun 2016 15:45:30 -0700 Subject: [PATCH 89/93] Added a new directory that will hold api json doc, started writing up my json docs --- api/docs.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 api/docs.json diff --git a/api/docs.json b/api/docs.json new file mode 100644 index 000000000..90ae96b29 --- /dev/null +++ b/api/docs.json @@ -0,0 +1,24 @@ +{ + "links": { + "customers": "http://localhost:3000/customers", + "customer_show": "http://localhost/customers/:name", + "customer_sort": "http://localhost/customers/sort/:field?n=[limit]p=[offset]", + "customer_current": "http://localhost/customers/:id/current", + "customer_history": "http://localhost/customers/:id/history" + }, + "data": [{ + "type": "customers", + "id": "1", + "attributes": { + "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" + }, + + }] +} From 90e9a3f1f31dde9789949a6cfc4f4e2c6064e1e4 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 24 Jun 2016 18:13:01 -0700 Subject: [PATCH 90/93] tried more tests for rentals. some are just not working out. --- lib/customers.js | 0 lib/movies.js | 0 lib/rentals.js | 0 models/rental.js | 11 +---- spec/models/rental.spec.js | 84 +++++++++++++++++++++++++++++++++++++- 5 files changed, 83 insertions(+), 12 deletions(-) delete mode 100644 lib/customers.js delete mode 100644 lib/movies.js delete mode 100644 lib/rentals.js diff --git a/lib/customers.js b/lib/customers.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/lib/movies.js b/lib/movies.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/lib/rentals.js b/lib/rentals.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/models/rental.js b/models/rental.js index 1a4174e52..8efb228cd 100644 --- a/models/rental.js +++ b/models/rental.js @@ -2,17 +2,8 @@ var app = require('../app') var db = app.get('db') var Movie = require('./movie') var Customer = require('./customer') -var Rental = require('./rental') -// var movieHistory = require('../db/rental_movie_history') - -var Rental = function (rental) { - this.id = rental.id - this.customer_id = rental.customer_id - this.movie_id = rental.movie_id - this.status = rental.status - this.return_date = rental.return_date -} +var Rental = function () {} Rental.all = function (callback) { db.movies.find (function (error, movies) { diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js index 181495615..674ca93fa 100644 --- a/spec/models/rental.spec.js +++ b/spec/models/rental.spec.js @@ -71,8 +71,6 @@ describe('Rental', function () { describe("#findCurrent", function () { it("should return current rentals for a customer", function (done) { Rental.findCurrent(29, function (error, movie) { - console.log(movie) - expect(movie.length).toEqual(3) expect(movie[0].id).toEqual(19) done() }) @@ -110,5 +108,87 @@ describe('Rental', function () { }) }) + describe("#findHistoryMovies", function () { + it("should return rental history for a movie", function (done) { + Rental.findHistoryMovies('Die Hard', function (error, rentals) { + expect(rentals.length).toEqual(2) + expect(rentals[0].id).toEqual(29) + done() + }) + }) + + it('should throw an error if no rentals found', function (done) { + Rental.findHistoryMovies("bad title", function(error, movie) { + expect(error).toEqual(null) + done() + }) + }) + }) + + describe("#find_customers", function () { + it("should return customers who rented a given movie", function (done) { + Rental.find_customers('Die Hard', function (error, customers) { + expect(customers.length).toEqual(2) + expect(customers[0].id).toEqual(19) + done() + }) + }) + + it('should throw an error if no customers found', function (done) { + Rental.findHistoryMovies("bad title", function(error, movie) { + expect(error).toEqual(null) + done() + }) + }) + }) + + describe("#checkout", function () { + it("should checkout correct movie and decrease movie inventory when checked out", function (done) { + var preStock; + Rental.find('Speed', function(error, movie) { + preStock = movie[0].inventory + }) + Rental.checkout("Speed", 29, function(error, movie){}) + Rental.find('Speed', function(error, movie) { + var postStock = movie[0].inventory + expect(movie[0].title).toEqual('Speed') + expect(postStock).toEqual(preStock - 1) + }) + done() + }) + + // Tests below here are some I tried but they are just not working. + // Leaving them in so Jeremy is aware we tried to finish them. + + // it("should not rent out movie when it's out of stock", function (done) { + // Rental.checkout("Deliverance", 9, function(error, movies){}) + // Rental.checkout("Deliverance", 9, function(error, movies){}) + // Rental.checkout("Deliverance", 9, function(error, movies){ + // expect(error).toBe(null) + // done() + // }) + // }) + }) + + // describe("#checkin", function () { + // it("should return correct movie and increase movie inventory when checkedin", function (done) { + // Rental.checkout("Rosemary's Baby", 29, function(error, movie){ + // }) + // Rental.checkin("Rosemary's Baby", 29, function(error, movie){}) + // Rental.find("Rosemary's Baby", function(error, movie) { + // var postStock = movie[0].inventory + // expect(postStock).toEqual(preStock + 1) + // }) + // done() + // }) + + // it("should not rent out movie when it's out of stock", function (done) { + // Rental.checkout("The Birds", 200, function(error, movie){}) + // Rental.checkout("The Birds", 200, function(error, movie){ + // expect(error.message).toEqual("No more copies available") + // }) + // done() + // }) + // }) }) From 79d1d86eac0d885c8ad1ccf94f4e073cfae5a343 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 24 Jun 2016 18:41:44 -0700 Subject: [PATCH 91/93] got another test working so up to 90% coverage for models --- models/rental.js | 3 +-- spec/models/rental.spec.js | 11 +++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/models/rental.js b/models/rental.js index 8efb228cd..d5d6c1810 100644 --- a/models/rental.js +++ b/models/rental.js @@ -104,8 +104,7 @@ Rental.checkin = function (title, cust_id, callback) { } Rental.overdueRental = function (callback) { - db.overdue_rentals(function (error, customers, movies, rentals) { - console.log(customers) + db.overdue_rentals(function (error, customers) { callback(null, customers.map (function (customer) { return customer })) diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js index 674ca93fa..8e785c154 100644 --- a/spec/models/rental.spec.js +++ b/spec/models/rental.spec.js @@ -170,6 +170,17 @@ describe('Rental', function () { // }) }) + describe("#overdueRental", function () { + it("should return list of customers with overdue rentals", function (done) { + Rental.overdueRental(function (error, customers) { + + expect(customers.length).toEqual(2) + }) + done() + }) + }) + + // describe("#checkin", function () { // it("should return correct movie and increase movie inventory when checkedin", function (done) { // Rental.checkout("Rosemary's Baby", 29, function(error, movie){ From a8a46030cfb4d796a1e8cb6d6e628224c56cd854 Mon Sep 17 00:00:00 2001 From: Jessica Date: Fri, 24 Jun 2016 18:45:00 -0700 Subject: [PATCH 92/93] cleaning up test file --- spec/models/rental.spec.js | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/spec/models/rental.spec.js b/spec/models/rental.spec.js index 8e785c154..e8acd1f3d 100644 --- a/spec/models/rental.spec.js +++ b/spec/models/rental.spec.js @@ -156,50 +156,15 @@ describe('Rental', function () { }) done() }) - - // Tests below here are some I tried but they are just not working. - // Leaving them in so Jeremy is aware we tried to finish them. - - // it("should not rent out movie when it's out of stock", function (done) { - // Rental.checkout("Deliverance", 9, function(error, movies){}) - // Rental.checkout("Deliverance", 9, function(error, movies){}) - // Rental.checkout("Deliverance", 9, function(error, movies){ - // expect(error).toBe(null) - // done() - // }) - // }) }) describe("#overdueRental", function () { it("should return list of customers with overdue rentals", function (done) { Rental.overdueRental(function (error, customers) { - - expect(customers.length).toEqual(2) + expect(customers.length).toEqual(2) }) done() }) }) - - // describe("#checkin", function () { - // it("should return correct movie and increase movie inventory when checkedin", function (done) { - // Rental.checkout("Rosemary's Baby", 29, function(error, movie){ - // }) - // Rental.checkin("Rosemary's Baby", 29, function(error, movie){}) - // Rental.find("Rosemary's Baby", function(error, movie) { - // var postStock = movie[0].inventory - // expect(postStock).toEqual(preStock + 1) - // }) - // done() - // }) - - // it("should not rent out movie when it's out of stock", function (done) { - // Rental.checkout("The Birds", 200, function(error, movie){}) - // Rental.checkout("The Birds", 200, function(error, movie){ - // expect(error.message).toEqual("No more copies available") - // }) - // done() - // }) - // }) - }) From 32e4fb07c4c51c110e8628bab5f898165e52bf6b Mon Sep 17 00:00:00 2001 From: Adriana Date: Sat, 25 Jun 2016 17:26:21 -0700 Subject: [PATCH 93/93] json docs --- api/docs.json | 113 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/api/docs.json b/api/docs.json index 90ae96b29..b347ba17e 100644 --- a/api/docs.json +++ b/api/docs.json @@ -19,6 +19,117 @@ "phone": "(322) 510-8695", "account_credit": "13.15" }, - + "type": "customers_show", + "id": "1", + "attributes": { + "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" + }, + "type": "customers_sort", + "field": "name", + "n": "number", + "p": "offset", + "attributes": { + "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" + }, + "type": "customers_current", + "id": "1", + "attributes": { + "id": 29, + "title": "The Shining", + "overview": "Jack Torrance accepts a caretaker job at the Overlook Hotel, where he, along with his wife Wendy and their son Danny, must live isolated from the rest of the world for the winter. But they aren't prepared for the madness that lurks within.", + "release_date": "1980-05-22", + "inventory": 3 + }, + "type": "customers_history", + "id": "1", + "attributes": { + "id": 29, + "title": "The Shining", + "overview": "Jack Torrance accepts a caretaker job at the Overlook Hotel, where he, along with his wife Wendy and their son Danny, must live isolated from the rest of the world for the winter. But they aren't prepared for the madness that lurks within.", + "release_date": "1980-05-22", + "inventory": 3 + } + }] +} + +{ + "links": { + "customers": "http://localhost:3000/movies", + "customer_show": "http://localhost/movies/sort/:field?n=[limit]p=offset", + "customer_sort": "http://localhost/movies/:title/current", + "customer_current": "http://localhost/movies/:title/history", + "customer_history": "http://localhost/movies/:id/history" + }, + "data": [{ + "type": "customers", + "id": "1", + "attributes": { + "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" + }, + "type": "customers_show", + "id": "1", + "attributes": { + "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" + }, + "type": "customers_sort", + "field": "name", + "n": "number", + "p": "offset", + "attributes": { + "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" + }, + "type": "customers_current", + "id": "1", + "attributes": { + "id": 29, + "title": "The Shining", + "overview": "Jack Torrance accepts a caretaker job at the Overlook Hotel, where he, along with his wife Wendy and their son Danny, must live isolated from the rest of the world for the winter. But they aren't prepared for the madness that lurks within.", + "release_date": "1980-05-22", + "inventory": 3 + }, + "type": "customers_history", + "id": "1", + "attributes": { + "id": 29, + "title": "The Shining", + "overview": "Jack Torrance accepts a caretaker job at the Overlook Hotel, where he, along with his wife Wendy and their son Danny, must live isolated from the rest of the world for the winter. But they aren't prepared for the madness that lurks within.", + "release_date": "1980-05-22", + "inventory": 3 + } }] }