249 lines
8.1 KiB
JavaScript
249 lines
8.1 KiB
JavaScript
/**
|
|
* Controller to manage the transactions functions
|
|
*/
|
|
'use strict';
|
|
|
|
var _ = require('lodash');
|
|
var httpStatus = require('http-status-codes');
|
|
var mongodb = require('mongodb');
|
|
var debug = require('debug')('webconsole-api:controllers:transactions');
|
|
var mainDB = require(global.pathPrefix + 'mainDB.js');
|
|
var swaggerUtils = require(global.pathPrefix + '../utils/swaggerUtils.js');
|
|
|
|
module.exports = {
|
|
getTransactions: getTransactions,
|
|
getTransaction: getTransaction
|
|
};
|
|
|
|
/**
|
|
* Get the transaction history
|
|
*
|
|
* @param {Object} req - Express request object
|
|
* @param {Object} res - Express response object
|
|
*/
|
|
function getTransactions(req, res) {
|
|
//
|
|
// Get the query params from the request and the session
|
|
//
|
|
var clientID = req.session.data.clientID;
|
|
var limit = req.swagger.params.limit.value;
|
|
var skip = req.swagger.params.skip.value;
|
|
var minDate = req.swagger.params.minDate.value;
|
|
var maxDate = req.swagger.params.maxDate.value;
|
|
var transactionTypes = req.swagger.params.transactionTypes.value;
|
|
var accountId = req.swagger.params.accountId.value;
|
|
|
|
var query = {
|
|
ClientID: clientID
|
|
};
|
|
//
|
|
// Add date limits if included
|
|
//
|
|
if (minDate || maxDate) {
|
|
query.SaleTime = {};
|
|
if (minDate) {
|
|
query.SaleTime.$gte = minDate;
|
|
}
|
|
if (maxDate) {
|
|
query.SaleTime.$lte = maxDate;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add accountId limits if any
|
|
//
|
|
if (accountId) {
|
|
query.AccountID = accountId;
|
|
}
|
|
|
|
//
|
|
// Limit to specific transaction types if requested
|
|
//
|
|
if (transactionTypes && _.isArray(transactionTypes)) {
|
|
query.TransactionType = {};
|
|
query.TransactionType.$in = transactionTypes;
|
|
}
|
|
|
|
//
|
|
// Define the projection based on the Swagger definition
|
|
//
|
|
var projection = swaggerUtils.swaggerToMongoProjection(
|
|
req.swagger.operation,
|
|
false // prevent _id being included
|
|
);
|
|
|
|
//
|
|
// Make the query. Not limit & skip have defaults defined in the
|
|
// swagger definition, so will always exist even if not requested
|
|
//
|
|
mainDB.collectionTransactionHistory.find(query, projection)
|
|
.skip(skip)
|
|
.limit(limit)
|
|
.sort({'SaleTime': -1}) // Hard-coded reverse sort by time
|
|
.toArray(function(err, items) {
|
|
if (err) {
|
|
debug('- failed to getTransactions', err);
|
|
res.status(httpStatus.BAD_GATEWAY).json({
|
|
code: 197,
|
|
info: 'Database offline'
|
|
});
|
|
} else {
|
|
//
|
|
// Move invoice number to the top level
|
|
//
|
|
for (var i = 0; i < items.length; ++i) {
|
|
if (!_.isUndefined(items[i].MerchantInvoiceNumber)) {
|
|
items[i].MerchantInvoiceNumber =
|
|
items[i].MerchantInvoiceNumber.InvoiceNumber;
|
|
}
|
|
}
|
|
|
|
res.status(httpStatus.OK).json(items);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Gets the transaction details for a specific transaction. The id is the
|
|
* `TransactionID` from the getTransactions() summary items.
|
|
*
|
|
* @param {Object} req - Express request object
|
|
* @param {Object} res - Express response object
|
|
*/
|
|
function getTransaction(req, res) {
|
|
//
|
|
// Get the query params from the request and the session
|
|
//
|
|
var clientID = req.session.data.clientID;
|
|
var transactionId = req.swagger.params.objectId.value;
|
|
|
|
//
|
|
// Build the query. The limits are:
|
|
// - Must match the id of the item we are looking for
|
|
// - Current user must be the customer or merchant (for security, to protect
|
|
// against Insecure Direct Object References).
|
|
//
|
|
var query = {
|
|
_id: mongodb.ObjectID(transactionId),
|
|
$or: [
|
|
{CustomerClientID: clientID},
|
|
{MerchantClientID: clientID}
|
|
]
|
|
};
|
|
|
|
//
|
|
// Depending on whether the user is a customer or merchant we convert some
|
|
// of the parameters to different names. This table defines these
|
|
// conversions.
|
|
// Note: any items not in this table, but in the swagger definition are
|
|
// assumed to come direct from the database unchanged.
|
|
//
|
|
const IS_CUSTOMER_INDEX = 0;
|
|
const IS_MERCHANT_INDEX = 1;
|
|
var conversions = {
|
|
// Structure is:
|
|
// ResponseField: [IsCustomerDbField, IsMerchantDbField]
|
|
//
|
|
OtherDisplayName: ['MerchantDisplayName', 'CustomerDisplayName'],
|
|
OtherSubDisplayName: ['MerchantSubDisplayName', 'CustomerSubDisplayName'],
|
|
OtherImage: ['MerchantImage', 'CustomerImage'],
|
|
MyLocation: ['CustomerLocation', 'MerchantLocation']
|
|
};
|
|
|
|
//
|
|
// Define the fields based on the Swagger definition.
|
|
// When going through the swagger definitions we check in the conversion
|
|
// table above, and fill in both fields so we have the required data to
|
|
// later do the conversion.
|
|
// Note: we allow _id here because the user provided it to us so no point
|
|
// hiding it.
|
|
//
|
|
var projection = {
|
|
// Initialise with client names to match against later on
|
|
MerchantClientID: 1,
|
|
CustomerClientID: 1
|
|
};
|
|
_.forEach(
|
|
req.swagger.operation.responses['200'].schema.properties,
|
|
_.bind(function(value, key, collection) {
|
|
if (conversions.hasOwnProperty(key)) {
|
|
// Has a conversion: include both
|
|
this[conversions[key][IS_CUSTOMER_INDEX]] = 1;
|
|
this[conversions[key][IS_MERCHANT_INDEX]] = 1;
|
|
} else {
|
|
// Doesn't have a conversion: include this one directly
|
|
this[key] = 1;
|
|
}
|
|
}, projection)
|
|
);
|
|
|
|
//
|
|
// Build the options to encapsulate the projection
|
|
//
|
|
var options = {
|
|
fields: projection,
|
|
comment: 'WebConsole:getTransaction' // For profiler logs use
|
|
};
|
|
|
|
//
|
|
// Make the request
|
|
//
|
|
mainDB.findOneObject(mainDB.collectionTransaction, query, options, false,
|
|
function(err, item) {
|
|
if (err) {
|
|
debug('- failed to getTransaction', err);
|
|
res.status(httpStatus.BAD_GATEWAY).json({
|
|
code: 197,
|
|
info: 'Database offline'
|
|
});
|
|
} else if (item === null) {
|
|
//
|
|
// Nothing found
|
|
//
|
|
res.status(httpStatus.NOT_FOUND).json({
|
|
code: 192,
|
|
info: 'Not found'
|
|
});
|
|
} else {
|
|
//
|
|
// Need to handle the conversions. Three step process:
|
|
// 1. Am 'I' the customer or merchant?
|
|
// - Must be one or other due to the search condition
|
|
// 2. Copy appropriate value from the DB name to the response name
|
|
// 3. Delete all DB name items
|
|
//
|
|
var conversionIndex = IS_CUSTOMER_INDEX;
|
|
if (item.MerchantClientID === clientID) {
|
|
conversionIndex = IS_MERCHANT_INDEX;
|
|
}
|
|
|
|
_.forEach(
|
|
conversions,
|
|
function(value, key, collection) {
|
|
item[key] = item[value[conversionIndex]];
|
|
});
|
|
|
|
_.forEach(
|
|
conversions,
|
|
function(value, key, collection) {
|
|
delete item[value[IS_CUSTOMER_INDEX]];
|
|
delete item[value[IS_MERCHANT_INDEX]];
|
|
});
|
|
|
|
// Delete the two hard-coded names we got for matching above
|
|
delete item.CustomerClientID;
|
|
delete item.MerchantClientID;
|
|
|
|
//
|
|
// Move invoice number to the top level
|
|
//
|
|
if (!_.isUndefined(item.MerchantInvoiceNumber)) {
|
|
item.MerchantInvoiceNumber =
|
|
item.MerchantInvoiceNumber.InvoiceNumber;
|
|
}
|
|
|
|
res.status(httpStatus.OK).json(item);
|
|
}
|
|
});
|
|
}
|