Skip to content
This repository has been archived by the owner on Feb 2, 2018. It is now read-only.

Commit

Permalink
Revert "Remove all listings (bug 957632)"
Browse files Browse the repository at this point in the history
This reverts commit 8f66386.
  • Loading branch information
kumar303 committed Jan 14, 2014
1 parent 483f3ae commit 246e171
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 26 deletions.
69 changes: 69 additions & 0 deletions docs/developer.rst
Expand Up @@ -20,6 +20,29 @@ Typically a payment provider will require more information about a seller that
is shown here, since the payment provider will likely want more information
pertinent to developer payouts.

.. http:get:: /sellers
**Response**

You get a list of all sellers. For example:

.. code-block:: json
[
{
"status": "ACTIVE",
"name": "John",
"email": "jdoe@example.org",
"resource_pk": "{seller-uuid}",
"resource_name": "sellers",
"resource_uri": "/sellers/{seller-uuid}",
"agreement": ""
},
...
]
:status 200: success.

.. http:get:: /sellers/:uuid
**Response**
Expand Down Expand Up @@ -128,6 +151,52 @@ This API allows you to get/create products that can be purchased. It is
required that a developer can register multiple products with the payment
provider.

.. http:get:: /products
**Request**

:param external_id:
Filter all products by this external identifier.
Since this is only unique per seller, filtering by
seller is probably a good idea.

:param seller_id:
Filter all products by this seller UUID, the
primary key for the :ref:`seller <sellers>` who owns each product.

**Response**

A list of products matching your query. For example:

.. code-block:: json
[
{
"external_id": "{product-uuid}",
"seller_id": "{seller-uuid}",
"active": true,
"name": "Magical Unicorn",
"resource_pk": "{product-uuid}",
"resource_name": "products",
"resource_uri": "/products/{product-uuid}"
}, {
...
}
]
In case of an error:

.. code-block:: json
{
"code": "InvalidArgument",
"message": "some error"
}
:status 200: success.
:status 404: resource not found.
:status 409: conflict.

.. http:post:: /products
**Request**
Expand Down
46 changes: 45 additions & 1 deletion lib/products.js
Expand Up @@ -6,9 +6,54 @@ var under = require('underscore');
var forms = require('./restforms');
var fields = forms.fields;
var models = exports.models = save('products');
var sellers = require('./sellers');
var z = require('./zutil');


var listProductsForm = forms.create({
/*jshint camelcase: false */
external_id: fields.string({
required: false,
}),
seller_id: fields.string({
required: false,
}),
});


exports.list = function(req, res, next) {
var query = {};

listProductsForm.promise(req)
.then(function(data) {
// Build a query from clean data of non-empty form field values.
Object.keys(data).forEach(function(k) {
if (data[k] !== '') {
query[k] = data[k];
}
});
if (query.seller_id) {
return Q.ninvoke(sellers.models, 'findOne', {_id: query.seller_id})
.then(function(seller) {
if (!seller) {
throw new errors.NotFoundError('seller with UUID ' + query.seller_id + ' not found');
}
query.seller_id = seller._id;
});
}
})
.then(function() {
return Q.ninvoke(models, 'find', query);
})
.then(function(products) {
res.send(products.map(z.serialize, 'products'));
})
.fail(function(err) {
next(err);
});
};


exports.retrieve = function(req, res, next) {
Q.ninvoke(models, 'findOne', {_id: req.params.uuid})
.then(function(product) {
Expand All @@ -24,7 +69,6 @@ exports.retrieve = function(req, res, next) {


var createProductForm = forms.create({
/*jshint camelcase: false */
name: fields.string({
required: true,
}),
Expand Down
10 changes: 10 additions & 0 deletions lib/sellers.js
Expand Up @@ -23,6 +23,16 @@ function withSeller(uuid, next, cb) {
}


exports.list = function(req, res, next) {
models.find({}, function (err, sellers) {
if (err) {
return next(err);
}
res.send(sellers.map(z.serialize, 'sellers'));
});
};


exports.retrieve = function(req, res, next) {
withSeller(req.params.uuid, next, function (err, seller) {
if (err) {
Expand Down
2 changes: 2 additions & 0 deletions lib/server.js
Expand Up @@ -82,8 +82,10 @@ function createApp(options) {
app.use(express.urlencoded());

app.post('/notices', notices.verify);
app.get('/products', products.list);
app.get('/products/:uuid', products.retrieve);
app.post('/products', products.create);
app.get('/sellers', sellers.list);
app.post('/sellers', sellers.create);
app.get('/sellers/:uuid', sellers.retrieve);
app.put('/sellers/:uuid', sellers.update);
Expand Down
160 changes: 160 additions & 0 deletions test/suite/products.test.js
@@ -1,3 +1,4 @@
var Q = require('q');
var uuid = require('node-uuid');

var Client = require('../client').Client;
Expand All @@ -9,6 +10,58 @@ var client = new Client('/products');
var anonymousClient = new AnonymousClient('/products');


function makeTwoProducts(t, extIds) {
var defer = Q.defer();

helpers.withSeller({}, function(seller) {
helpers.withProduct({
/*jshint camelcase: false */
seller_id: seller._id,
external_id: extIds.pop(),
name: 'x',
}, function(product1) {
helpers.withProduct({
/*jshint camelcase: false */
seller_id: seller._id,
external_id: extIds.pop(),
name: 'x',
}, function(product2) {
defer.resolve({
products: [product1, product2],
seller: seller,
});
});
});
});

return defer.promise;
}


function makeTwoSellers(t, extIds) {
var defer = Q.defer();
var seller1;
var seller2;

makeTwoProducts(t, extIds)
.then(function(result1) {
seller1 = result1.seller;
return makeTwoProducts(t, extIds);
})
.then(function(result2) {
seller2 = result2.seller;
})
.then(function() {
defer.resolve([seller1, seller2]);
})
.fail(function(err) {
defer.reject(err);
});

return defer.promise;
}


exports.setUp = function(done) {
products.models.deleteMany({}, done);
};
Expand Down Expand Up @@ -232,3 +285,110 @@ exports.retrieveNoProduct = function(t) {
t.done();
});
};


exports.listAllProducts = function(t) {
makeTwoProducts(t, ['one', 'two'])
.then(function() {
var extIds = [];
client
.get()
.expect(200)
.end(function(err, res) {
t.ifError(err);
res.body.forEach(function(ob) {
/*jshint camelcase: false */
extIds.push(ob.external_id);
});
extIds.sort();
t.equal(extIds[0], 'one');
t.equal(extIds[1], 'two');
t.done();
});
})
.fail(function(err) {
t.ifError(err);
t.done();
});
};


exports.filterProductsByExtId = function(t) {
makeTwoProducts(t, ['one', 'two'])
.then(function() {
client
.get({
/*jshint camelcase: false */
external_id: 'one',
})
.expect(200)
.end(function(err, res) {
t.ifError(err);
t.equal(res.body[0].external_id, 'one');
t.equal(res.body.length, 1);
t.done();
});
})
.fail(function(err) {
t.ifError(err);
t.done();
});
};


exports.filterProductsBySeller = function(t) {
makeTwoSellers(t, ['one', 'two'])
.then(function(sellersResult) {
client
.get({
/*jshint camelcase: false */
external_id: 'one',
seller_id: sellersResult[0].resource_pk,
})
.expect(200)
.end(function(err, res) {
t.ifError(err);
t.equal(res.body.length, 1);
t.equal(res.body[0].external_id, 'one');
t.equal(res.body[0].seller_id, sellersResult[0]._id);
t.done();
});
})
.fail(function(err) {
t.ifError(err);
t.done();
});
};


exports.filterByWrongSeller = function(t) {
makeTwoProducts(t, ['one', 'two'])
.then(function() {
client
.get({
/*jshint camelcase: false */
seller_id: 'invalid',
external_id: 'one',
})
.expect(404)
.end(function(err) {
t.ifError(err);
t.done();
});
})
.fail(function(err) {
t.ifError(err);
t.done();
});
};


exports.wrongParamIsError = function(t) {
client
.get({badParam: 'nope'})
.expect(409)
.end(function(err) {
t.ifError(err);
t.done();
});
};
27 changes: 27 additions & 0 deletions test/suite/sellers.test.js
Expand Up @@ -52,6 +52,33 @@ exports.createSellerWithoutStatus = function(t) {
};


exports.retrieveSellers = function(t) {
helpers.withSeller({}, function(seller) {
client
.get()
.expect(200)
.end(function(err, res) {
t.ifError(err);
/*jshint camelcase: false */
t.equal(res.body[0].resource_pk, seller._id);
t.done();
});
});
};


exports.retrieveSellersEmpty = function(t) {
client
.get()
.expect(200)
.end(function(err, res) {
t.ifError(err);
t.equal(res.body.length, 0);
t.done();
});
};


exports.retrieveSeller = function(t) {
helpers.withSeller({}, function(seller) {
var client = new Client('/sellers/' + seller._id);
Expand Down

0 comments on commit 246e171

Please sign in to comment.