diff --git a/actions/payments.js b/actions/payments.js new file mode 100755 index 000000000..d966cabd7 --- /dev/null +++ b/actions/payments.js @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2014 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author hesibo + */ +"use strict"; + +var async = require('async'); +var _ = require('underscore'); + +var IllegalArgumentError = require("../errors/IllegalArgumentError"); + +/** + * Represents a predefined list of valid sort column. + */ +var ALLOWABLE_SORT_COLUMN = ["description", "type", "createDate", "releaseDate", "paidDate", "status", "amount"]; + +/** + * Represents a predefined map of valid sort column mapping to database column name. + */ +var SORT_COLUMN = { + description : "description", + type : "type", + createdate : "date_create", + releasedate : "release_date", + paiddate : "paid_date", + status : "status", + amount : "amount" +}; + +/** + * The date format for output date field. + */ +var OUTPUT_DATE_FORMAT = "MM/DD/YYYY"; + +/** + * Checks whether given array is empty. + * + * @param obj - the object + * @param objName - the object name + * @return {Error} if invalid or null if valid. + */ +function checkEmptyArray(obj, objName) { + if (obj.length === 0) { + return new IllegalArgumentError("The " + objName + " parameter is incorrect."); + } + return null; +} + +/** + * Checks whether given string is empty when it is defined. + * + * @param obj - the string + * @param objName - the string name + * @return {Error} if invalid or null if valid. + */ +function checkString(obj, objName) { + if (_.isDefined(obj) && obj.trim().length === 0) { + return new IllegalArgumentError("The " + objName + " parameter should be no-empty string."); + } + return null; +} + +/** + * This function search payments and get payment summary. + * + * @param {Object} api - The api object that is used to access the global infrastructure + * @param {Object} connection - The connection object for the current request + * @param {Function} next - The callback to be called after this function is done + */ +var searchPayments = function (api, connection, next) { + var error, i, + helper = api.helper, + pageIndex = Number(connection.params.pageIndex || 1), + pageSize = Number(connection.params.pageSize || 10), + status = connection.params.status, + type = connection.params.type, + sortColumn = (connection.params.sortColumn || "createDate").toLowerCase(), + sortOrder = (connection.params.sortOrder || "asc").toLowerCase(), + sqlParams = {}, + result = {}, + execQuery = function (name) { + return function (cbx) { + api.dataAccess.executeQuery(name, sqlParams, connection.dbConnectionMap, cbx); + }; + }; + async.waterfall([ + function (cb) { + sqlParams.paymentStatusIds = []; + var id; + for (id in helper.PAYMENT_STATUS) { + if (helper.PAYMENT_STATUS.hasOwnProperty(id) && (_.isUndefined(status) || helper.PAYMENT_STATUS[id].toLowerCase() === status.toLowerCase())) { + sqlParams.paymentStatusIds.push(id); + } + } + + error = helper.checkPositiveInteger(pageIndex, "pageIndex") + || helper.checkMaxInt(pageIndex, "pageIndex") + || helper.checkPositiveInteger(pageSize, "pageSize") + || helper.checkMaxInt(pageSize, "pageSize") + || helper.checkMember(connection) + || helper.checkContains(["asc", "desc"], sortOrder.toLowerCase(), "sortOrder") + || helper.checkSortColumn(ALLOWABLE_SORT_COLUMN, sortColumn) + || checkString(type, "type") + || checkEmptyArray(sqlParams.paymentStatusIds, "status"); + if (error) { + cb(error); + return; + } + + sqlParams.userId = connection.caller.userId; + sqlParams.type = type; + sqlParams.firstRowIndex = (pageIndex - 1) * pageSize; + sqlParams.pageSize = pageSize; + sqlParams.sortColumn = SORT_COLUMN[sortColumn]; + sqlParams.sortOrder = sortOrder; + + async.parallel({ + count: _.isUndefined(type) ? execQuery("get_payment_count") : execQuery("get_payment_count_with_type"), + payments: _.isUndefined(type) ? execQuery("get_payments") : execQuery("get_payments_with_type"), + summary: execQuery("get_payment_summary") + }, cb); + }, + function (results, cb) { + result.total = results.count[0].total; + result.pageIndex = pageIndex; + result.pageSize = pageSize; + result.payments = _.map(results.payments, function (payment) { + return { + description : payment.description.trim(), + type : payment.type, + createDate : helper.formatDate(payment.date_create, OUTPUT_DATE_FORMAT), + releaseDate : helper.formatDate(payment.release_date, OUTPUT_DATE_FORMAT), + paidDate : helper.formatDate(payment.paid_date, OUTPUT_DATE_FORMAT) || "", + status : payment.status, + amount : payment.amount + }; + }); + if (results.summary.length === 0) { + result.summary = { + paid : 0 + }; + } else { + result.summary = {}; + } + results.summary.forEach(function (element) { + var list = element.status.split(" "); + for (i = 0; i < list.length; i = i + 1) { + list[i] = (i === 0 ? list[i].substr(0, 1).toLowerCase() : list[i].substr(0, 1).toUpperCase()) + list[i].substr(1); + } + result.summary[list.join("")] = element.sum; + }); + cb(); + } + ], function (err) { + if (err) { + helper.handleError(api, connection, err); + } else { + connection.response = result; + } + next(connection, true); + }); +}; + +/** + * get payment list API. + */ +exports.getPaymentList = { + "name": "getPaymentList", + "description": "get payment list api", + inputs: { + required: [], + optional: ["status", "type", "pageIndex", "pageSize", "sortColumn", "sortOrder"] + }, + blockedConnectionTypes: [], + outputExample: {}, + version: 'v2', + transaction : 'read', // this action is read-only + cacheEnabled : true, + databases : ["informixoltp"], + run: function (api, connection, next) { + if (connection.dbConnectionMap) { + api.log("Execute searchPayments#run", 'debug'); + searchPayments(api, connection, next); + } else { + api.helper.handleNoConnection(api, connection, next); + } + } +}; \ No newline at end of file diff --git a/apiary.apib b/apiary.apib index d98561495..bcb607c9f 100644 --- a/apiary.apib +++ b/apiary.apib @@ -7782,13 +7782,20 @@ Payments APIs ### Payment List [GET] + Parameters - + status (optional, string, `Paid`) ... Payment Status: Paid, Owed, Cancelled, Entered into payment system + + status (optional, string, `Paid`) ... Payment Status: Paid, Owed, Cancelled, Entered into payment system, etc.. + type (optional, string, `Contest Payment`) ... Payment Type: Contest Payment, Review Payment, Copilot Payment, etc.. - + pageIndex (optional, number, `1`) ... The page index of the returned resources. 1-based. It can be null. The default value will be 1 + + pageIndex (optional, number, `1`) ... The page index of the returned resources. 1-based. It can be null. The default value will be 1. + pageSize (optional, number, `50`) ... The page size of the returned resources. 1-based. It can be null. The default value will be 10. - + sortColumn (optional, string, `description`) ... The column name to sort, can be null. - + sortOrder (optional, string, `asc`) ... The sorting order, can be null. If it's set, it can only be 'asc' or 'desc'. - + + sortColumn (optional, string, `description`) ... The column name to sort, can be null. The default value will be 'createDate'. + + sortOrder (optional, string, `asc`) ... The sorting order, can be null. If it's set, it can only be 'asc' or 'desc'. The default value will be 'asc'. + ++ Request + + + Headers + + Authorization : Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZHwxMzI0NTYiLCJleHAiOjEzOTI4MTc4ODQsImF1ZCI6InRvcGNvZGVyIiwiaWF0IjoxMzkyNzU3ODg0fQ.7X2IKkiyyI1ExSM5GNpdhJ8fGGK5-oAjzccX6YL_BKY + + + Response 200 (application/json) { @@ -7800,17 +7807,19 @@ Payments APIs "description": "[TCCC-4789] - Cockpit Instant Search Task", "type": "Contest Payment", "createDate": "12/13/2012", - "releaseDate": "13/01/1012", + "releaseDate": "01/13/2013", + "paidDate": "02/30/2013", "status": "Paid", "amount": 250 }, { "description": "(Application, v1.0) TC API - Studio Challenge Result API Update - First2Finish review board", "type": "Review Board Payment", - "createDate": "12/13/2012", - "releaseDate": "13/01/1012", + "createDate": "12/15/2012", + "releaseDate": "01/15/2013", + "paidDate": "02/30/2013", "status": "Paid", - "amount": 3 + "amount": 123 } ], "summary": { @@ -7820,51 +7829,58 @@ Payments APIs "enteredIntoPaymentSystem": 50.0 } } - + Response 400 (application/json) { "name":"Bad Request", "value":"400", - "description":"This message will explain why the request is invalid or cannot be served." + "description":"The request was invalid. An accompanying message will explain why." + "description":"pageIndex should be number." } -+ Response 404 (application/json) ++ Response 400 (application/json) { - "name":"Not Found", - "value":"404", - "description":"This message will explain why the URI requested is invalid or the resource does not exist." + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + "description":"pageIndex should be positive." } -+ Response 500 (application/json) ++ Response 400 (application/json) { - "name":"Internal Server Error", - "value":"500", - "description":"Unknown server error. Please contact support." + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + "description":"pageIndex should be less or equal to 2147483647." } -+ Response 503 (application/json) ++ Response 400 (application/json) { - "name":"Service Unavailable", - "value":"503", - "description":"Servers are up but overloaded. Try again later." + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + "description":"pageSize should be number." } -## Docusign Callback [/terms/docusignCallback] -### Docusign Callback [POST] ++ Response 400 (application/json) -+ Parameters - + envelopeStatus (required, String, `Complete`) ... The status of the envelope - + envelopeId (required, UUID, `9103DC77-D8F1-4D7B-BED1-6116604EE98C`) ... The envelope to process - + tabs (required, Array, [{tabLabel: 'Handle', tabValue: 'anix'}, {...}]) ... The tab values. Can be empty - + connectKey (required, String, 'ABCDED-12435-EDFADSEC') The conenct key + { + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + "description":"pageSize should be positive." + } + ++ Response 400 (application/json) -+ Response 200 (application/json) { - "message": "some message" + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + "description":"pageSize should be less or equal to 2147483647." } + Response 400 (application/json) @@ -7873,14 +7889,43 @@ Payments APIs "name":"Bad Request", "value":"400", "description":"The request was invalid. An accompanying message will explain why." + "description":"The sort column 'invalid' is invalid, it should be element of description,type,createDate,releaseDate,paidDate,status,amount." } -+ Response 404 (application/json) ++ Response 400 (application/json) { - "name":"Not Found", - "value":"404", - "description":"This message will explain why the URI requested is invalid or the resource does not exist." + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + "description":"sortOrder should be an element of asc,desc." + } + ++ Response 400 (application/json) + + { + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + "description":"The type parameter is incorrect." + } + ++ Response 400 (application/json) + + { + "name":"Bad Request", + "value":"400", + "description":"The request was invalid. An accompanying message will explain why." + "description":"The status parameter is incorrect." + } + ++ Response 401 (application/json) + + { + "name":"Unauthorized", + "value":"401", + "description":"Authentication credentials were missing or incorrect." + "details:":"Unauthorized Error" } + Response 500 (application/json) diff --git a/docs/Module Assembly - TopCoder NodeJS Payment List API.doc b/docs/Module Assembly - TopCoder NodeJS Payment List API.doc new file mode 100755 index 000000000..707108f18 Binary files /dev/null and b/docs/Module Assembly - TopCoder NodeJS Payment List API.doc differ diff --git a/initializers/helper.js b/initializers/helper.js index ed0202905..c520648d0 100644 --- a/initializers/helper.js +++ b/initializers/helper.js @@ -6,7 +6,7 @@ /** * This module contains helper functions. * @author Sky_, Ghost_141, muzehyun, kurtrips, isv, LazyChild, hesibo - * @version 1.23 + * @version 1.24 * changes in 1.1: * - add mapProperties * changes in 1.2: @@ -66,6 +66,10 @@ * - add validatePassword method. * - introduce the stringUtils in this file. * - add PASSWORD_HASH_KEY. + * changes in 1.24 + * - add PAYMENT_STATUS + * - add checkSortColumn function + * - update formatDate function */ "use strict"; @@ -120,6 +124,19 @@ helper.both = { category: [1, 2, 3] }; +/** + * payment status + */ +helper.PAYMENT_STATUS = { + 53 : 'Paid', + 55 : 'On Hold', + 56 : 'Owed', + 65 : 'Cancelled', + 68 : 'Expired', + 70 : 'Entered into payment system', + 71 : 'Accruing' +}; + /** * The max value for integer. */ @@ -1155,7 +1172,7 @@ helper.checkDates = function (startDate, endDate) { */ helper.formatDate = function (date, format) { if (date) { - return date.substring(0, format.length); + return moment(date).format(format); } return ''; }; @@ -1284,6 +1301,26 @@ helper.getFileTypes = function (api, dbConnectionMap, callback) { }); }; +/** + * Check sort column. + * + * @param {Array} sortColumns - the valid sort columns list. + * @param {Object} sortColumn - the sort column to check. + * @return {Error} if input not valid. + * + * @since 1.24 + */ +helper.checkSortColumn = function (sortColumns, sortColumn) { + var error = helper.checkArray(sortColumns, "sortColumns"); + if (error) { + return error; + } + if (helper.getLowerCaseList(sortColumns).indexOf(sortColumn) === -1) { + return new IllegalArgumentError("The sort column '" + sortColumn + "' is invalid, it should be element of " + sortColumns + "."); + } + return null; +}; + /* * this is the random int generator class */ diff --git a/queries/get_payment_count b/queries/get_payment_count new file mode 100755 index 000000000..32836444a --- /dev/null +++ b/queries/get_payment_count @@ -0,0 +1,8 @@ +SELECT + count(*) AS total +FROM payment p, + payment_detail pd +WHERE p.most_recent_detail_id = pd.payment_detail_id + AND pd.payment_type_id NOT IN (3, 5) + AND p.user_id = @userId@ + AND pd.payment_status_id IN (@paymentStatusIds@) \ No newline at end of file diff --git a/queries/get_payment_count.json b/queries/get_payment_count.json new file mode 100755 index 000000000..0bdb05a09 --- /dev/null +++ b/queries/get_payment_count.json @@ -0,0 +1,5 @@ +{ + "name" : "get_payment_count", + "db" : "informixoltp", + "sqlfile" : "get_payment_count" +} diff --git a/queries/get_payment_count_with_type b/queries/get_payment_count_with_type new file mode 100755 index 000000000..ac2011949 --- /dev/null +++ b/queries/get_payment_count_with_type @@ -0,0 +1,11 @@ +SELECT + count(*) AS total +FROM payment p, + payment_detail pd, + payment_type_lu pt +WHERE p.most_recent_detail_id = pd.payment_detail_id + AND pd.payment_type_id NOT IN (3, 5) + AND pd.payment_type_id = pt.payment_type_id + AND p.user_id = @userId@ + AND LOWER(pt.payment_type_desc) = LOWER('@type@') + AND pd.payment_status_id IN (@paymentStatusIds@) \ No newline at end of file diff --git a/queries/get_payment_count_with_type.json b/queries/get_payment_count_with_type.json new file mode 100755 index 000000000..269e138a0 --- /dev/null +++ b/queries/get_payment_count_with_type.json @@ -0,0 +1,5 @@ +{ + "name" : "get_payment_count_with_type", + "db" : "informixoltp", + "sqlfile" : "get_payment_count_with_type" +} diff --git a/queries/get_payment_summary b/queries/get_payment_summary new file mode 100755 index 000000000..e1dd386c9 --- /dev/null +++ b/queries/get_payment_summary @@ -0,0 +1,12 @@ +SELECT + ps.payment_status_desc AS status, + SUM(pd.net_amount) AS sum +FROM payment p, + payment_detail pd, + payment_status_lu ps +WHERE p.most_recent_detail_id = pd.payment_detail_id + AND pd.payment_status_id = ps.payment_status_id + AND pd.payment_type_id NOT IN (3, 5) + AND ps.payment_status_id <> 69 + AND p.user_id = @userId@ +GROUP BY 1 \ No newline at end of file diff --git a/queries/get_payment_summary.json b/queries/get_payment_summary.json new file mode 100755 index 000000000..722001a3d --- /dev/null +++ b/queries/get_payment_summary.json @@ -0,0 +1,5 @@ +{ + "name" : "get_payment_summary", + "db" : "informixoltp", + "sqlfile" : "get_payment_summary" +} diff --git a/queries/get_payments b/queries/get_payments new file mode 100755 index 000000000..d70838387 --- /dev/null +++ b/queries/get_payments @@ -0,0 +1,26 @@ +SELECT +SKIP @firstRowIndex@ +FIRST @pageSize@ + pd.payment_desc || + (CASE WHEN pt.payment_type_id IN (6, 7) AND pd.gross_amount <> pd.total_amount THEN + '(' || TO_CHAR(pd.installment_number) || + (CASE pd.installment_number WHEN 1 THEN 'st' WHEN 2 THEN 'nd' WHEN 3 THEN 'rd' ELSE 'th' END) || + ' installment, total amount=' || TO_CHAR(pd.total_amount) || ')' + ELSE '' END) AS description, + pt.payment_type_desc AS type, + p.create_date AS date_create, + pd.date_due AS release_date, + pd.date_paid AS paid_date, + ps.payment_status_desc AS status, + pd.net_amount AS amount +FROM payment p, + payment_detail pd, + payment_type_lu pt, + payment_status_lu ps +WHERE p.most_recent_detail_id = pd.payment_detail_id + AND pd.payment_type_id = pt.payment_type_id + AND pd.payment_status_id = ps.payment_status_id + AND pt.payment_type_id NOT IN (3, 5) + AND p.user_id = @userId@ + AND ps.payment_status_id IN (@paymentStatusIds@) +ORDER BY @sortColumn@ @sortOrder@ \ No newline at end of file diff --git a/queries/get_payments.json b/queries/get_payments.json new file mode 100755 index 000000000..6d7bb0372 --- /dev/null +++ b/queries/get_payments.json @@ -0,0 +1,5 @@ +{ + "name" : "get_payments", + "db" : "informixoltp", + "sqlfile" : "get_payments" +} diff --git a/queries/get_payments_with_type b/queries/get_payments_with_type new file mode 100755 index 000000000..2cf612a67 --- /dev/null +++ b/queries/get_payments_with_type @@ -0,0 +1,27 @@ +SELECT +SKIP @firstRowIndex@ +FIRST @pageSize@ + pd.payment_desc || + (CASE WHEN pt.payment_type_id IN (6, 7) AND pd.gross_amount <> pd.total_amount THEN + '(' || TO_CHAR(pd.installment_number) || + (CASE pd.installment_number WHEN 1 THEN 'st' WHEN 2 THEN 'nd' WHEN 3 THEN 'rd' ELSE 'th' END) || + ' installment, total amount=' || TO_CHAR(pd.total_amount) || ')' + ELSE '' END) AS description, + pt.payment_type_desc AS type, + p.create_date AS date_create, + pd.date_due AS release_date, + pd.date_paid AS paid_date, + ps.payment_status_desc AS status, + pd.net_amount AS amount +FROM payment p, + payment_detail pd, + payment_type_lu pt, + payment_status_lu ps +WHERE p.most_recent_detail_id = pd.payment_detail_id + AND pd.payment_type_id = pt.payment_type_id + AND pd.payment_status_id = ps.payment_status_id + AND pt.payment_type_id NOT IN (3, 5) + AND p.user_id = @userId@ + AND ps.payment_status_id IN (@paymentStatusIds@) + AND LOWER(pt.payment_type_desc) = LOWER('@type@') +ORDER BY @sortColumn@ @sortOrder@ \ No newline at end of file diff --git a/queries/get_payments_with_type.json b/queries/get_payments_with_type.json new file mode 100755 index 000000000..a593140f6 --- /dev/null +++ b/queries/get_payments_with_type.json @@ -0,0 +1,5 @@ +{ + "name" : "get_payments_with_type", + "db" : "informixoltp", + "sqlfile" : "get_payments_with_type" +} diff --git a/routes.js b/routes.js index 1927a1554..f69ac9647 100755 --- a/routes.js +++ b/routes.js @@ -1,8 +1,8 @@ /* * Copyright (C) 2013 - 2014 TopCoder Inc., All Rights Reserved. * - * @version 1.34 - * @author vangavroche, Sky_, muzehyun, kurtrips, Ghost_141, ecnu_haozi, hesibo, LazyChild, bugbuka, isv + * @version 1.36 + * @author vangavroche, Sky_, muzehyun, kurtrips, Ghost_141, ecnu_haozi, hesibo, LazyChild, bugbuka, isv, flytoj2ee * Changes in 1.1: * - add routes for search challenges * Changes in 1.2: @@ -80,6 +80,10 @@ * - add route for apply develop review opportunities api. * changes in 1.34: * - added route for client active challenge costs + * changes in 1.35: + * - added route for auth0 callback api + * Changes in 1.36 + * - add route for get payment list api. */ /* --------------------- @@ -221,13 +225,17 @@ exports.routes = { { path: "/:apiVersion/bugs", action: "bugs" }, { path: "/:apiVersion/validation/sso", action: "ssoValidation" }, + + { path: "/:apiVersion/payments", action: "getPaymentList" }, //Stubs APIs { path: "/:apiVersion/data/reviewOpportunities/:id", action: "getAlgorithmsReviewOpportunity" }, { path: "/:apiVersion/data/reviewOpportunities", action: "getAlgorithmsReviewOpportunities" }, { path: "/:apiVersion/software/reviewers/:contestType", action: "getChallengeReviewers" }, { path: "/:apiVersion/design/statistics/tops/:challengeType", action: "getStudioTops" }, - { path: "/:apiVersion/data/challengetypes", action: "algorithmsChallengeTypes" } + { path: "/:apiVersion/data/challengetypes", action: "algorithmsChallengeTypes" }, + + { path: "/:apiVersion/auth0/callback", action: "auth0Callback" } ].concat(testMethods.get), post: [ // Stub API diff --git a/test/sqls/payments/informixoltp__clean b/test/sqls/payments/informixoltp__clean new file mode 100755 index 000000000..b72aa55cd --- /dev/null +++ b/test/sqls/payments/informixoltp__clean @@ -0,0 +1,2 @@ +DELETE FROM payment WHERE payment_id > 1000; +DELETE FROM payment_detail WHERE payment_detail_id > 1000; diff --git a/test/sqls/payments/informixoltp__insert_test_data b/test/sqls/payments/informixoltp__insert_test_data new file mode 100755 index 000000000..5e2278685 --- /dev/null +++ b/test/sqls/payments/informixoltp__insert_test_data @@ -0,0 +1,52 @@ +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1001, 450, to_date('2014-04-08T10:01:04','%Y-%m-%dT%H:%M:%S'), NULL, 53, 'contest 2 1st place', 65, to_date('2014-03-20T10:01:04','%Y-%m-%dT%H:%M:%S'), to_date('2014-02-18T10:01:05','%Y-%m-%dT%H:%M:%S'), NULL, NULL); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1001, 132456, 1001, to_date('2014-02-18T10:01:05','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1002, 150, to_date('2014-04-08T10:01:05','%Y-%m-%dT%H:%M:%S'), NULL, 53, 'contest 2 1st place', 65, to_date('2014-03-20T10:01:05','%Y-%m-%dT%H:%M:%S'), to_date('2014-02-18T10:01:06','%Y-%m-%dT%H:%M:%S'), NULL, NULL); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1002, 132456, 1002, to_date('2014-02-18T10:01:06','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1003, 600, to_date('2014-04-08T10:01:07','%Y-%m-%dT%H:%M:%S'), NULL, 53, 'contest 3 1st place', 65, to_date('2014-03-30T10:01:07','%Y-%m-%dT%H:%M:%S'), to_date('2014-02-28T10:01:08','%Y-%m-%dT%H:%M:%S'), NULL, NULL); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1003, 132456, 1003, to_date('2014-02-28T10:01:08','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1004, 200, to_date('2014-04-08T10:01:09','%Y-%m-%dT%H:%M:%S'), NULL, 53, 'contest 3 1st place', 65, to_date('2014-03-30T10:01:09','%Y-%m-%dT%H:%M:%S'), to_date('2014-02-28T10:01:12','%Y-%m-%dT%H:%M:%S'), NULL, NULL); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1004, 132456, 1004, to_date('2014-02-28T10:01:12','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1005, 500, to_date('2014-04-08T10:01:12','%Y-%m-%dT%H:%M:%S'), NULL, 53, 'contest 4 2nd place', 65, to_date('2014-04-04T10:01:12','%Y-%m-%dT%H:%M:%S'), to_date('2014-02-28T10:01:13','%Y-%m-%dT%H:%M:%S'), NULL, NULL); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1005, 132456, 1005, to_date('2014-02-28T10:01:13','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1006, 300, NULL, NULL, 56, 'contest 1 1st place', 65, to_date('2014-04-19T10:01:14','%Y-%m-%dT%H:%M:%S'), to_date('2014-03-20T10:01:15','%Y-%m-%dT%H:%M:%S'), NULL, NULL); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1006, 132456, 1006, to_date('2014-03-20T10:01:15','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1007, 100, NULL, NULL, 56, 'contest 1 1st place', 65, to_date('2014-04-19T10:01:15','%Y-%m-%dT%H:%M:%S'), to_date('2014-03-20T10:01:16','%Y-%m-%dT%H:%M:%S'), NULL, NULL); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1007, 132456, 1007, to_date('2014-03-20T10:01:16','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1008, 250, NULL, 250, 56, 'component 1 1st place', 6, to_date('2014-04-29T10:01:18','%Y-%m-%dT%H:%M:%S'), to_date('2014-03-30T10:01:18','%Y-%m-%dT%H:%M:%S'), 400, 1); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1008, 132456, 1008, to_date('2014-03-30T10:01:18','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1009, 150, NULL, 150, 56, 'component 1 1st place', 6, to_date('2014-04-29T10:01:19','%Y-%m-%dT%H:%M:%S'), to_date('2014-03-30T10:01:20','%Y-%m-%dT%H:%M:%S'), 400, 2); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1009, 132456, 1009, to_date('2014-03-30T10:01:20','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1010, 435.24, NULL, NULL, 70, '2014 February Development Track Top Performers 10th place', 41, to_date('2014-04-06T10:01:20','%Y-%m-%dT%H:%M:%S'), to_date('2014-03-22T10:01:22','%Y-%m-%dT%H:%M:%S'), NULL, NULL); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1010, 132456, 1010, to_date('2014-03-22T10:01:22','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1011, 20.15, NULL, NULL, 70, '2014 February Development Track Top Performers 10th place (taxable)', 63, to_date('2014-04-06T10:01:22','%Y-%m-%dT%H:%M:%S'), to_date('2014-03-22T10:01:23','%Y-%m-%dT%H:%M:%S'), NULL, NULL); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1011, 132456, 1011, to_date('2014-03-22T10:01:23','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1012, 225, NULL, NULL, 71, 'contest review 1', 7, to_date('2014-05-09T10:01:24','%Y-%m-%dT%H:%M:%S'), to_date('2014-04-09T10:01:24','%Y-%m-%dT%H:%M:%S'), NULL, NULL); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1012, 132456, 1012, to_date('2014-04-09T10:01:24','%Y-%m-%dT%H:%M:%S')); +INSERT INTO payment_detail(payment_detail_id, net_amount, date_paid, gross_amount, payment_status_id, payment_desc, payment_type_id, date_due, create_date, total_amount, installment_number) +VALUES(1013, 50, NULL, NULL, 71, 'spec review 1', 27, to_date('2014-05-09T10:01:25','%Y-%m-%dT%H:%M:%S'), to_date('2014-04-09T10:01:26','%Y-%m-%dT%H:%M:%S'), NULL, NULL); +INSERT INTO payment(payment_id, user_id, most_recent_detail_id, create_date) +VALUES(1013, 132456, 1013, to_date('2014-04-09T10:01:26','%Y-%m-%dT%H:%M:%S')); diff --git a/test/test.payments.js b/test/test.payments.js new file mode 100755 index 000000000..832773c88 --- /dev/null +++ b/test/test.payments.js @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2014 TopCoder Inc., All Rights Reserved. + * + * @version 1.0 + * @author TCSASSEMBLER + */ +"use strict"; +/*global describe, it, before, beforeEach, after, afterEach, __dirname */ +/*jslint node: true, stupid: true, unparam: true */ + +/** + * Module dependencies. + */ +var request = require('supertest'); +var assert = require('chai').assert; +var async = require('async'); +var testHelper = require('./helpers/testHelper'); + +var API_ENDPOINT = process.env.API_ENDPOINT || 'http://localhost:8080'; +var SQL_DIR = __dirname + "/sqls/payments/"; + +describe("Payment List API", function () { + this.timeout(60000); // The api with testing remote db could be quit slow + + var heffanAuthHeader = testHelper.generateAuthHeader({ sub: "ad|132456" }), + userAuthHeader = testHelper.generateAuthHeader({ sub: "ad|132458" }); + + /** + * Clear database + * @param {Function} done the callback + */ + function clearDb(done) { + testHelper.runSqlFile(SQL_DIR + "informixoltp__clean", "informixoltp", done); + } + + /** + * This function is run before all tests. + * Generate tests data. + * @param {Function} done the callback + */ + before(function (done) { + async.waterfall([ + clearDb, + function (cb) { + testHelper.runSqlFile(SQL_DIR + "informixoltp__insert_test_data", "informixoltp", cb); + } + ], done); + }); + + /** + * This function is run after all tests. + * Clean up all data. + * @param {Function} done the callback + */ + after(function (done) { + clearDb(done); + }); + + /** + * Create request and return it + * @param {String} queryString - the query string + * @param {String} authHeader - the Authorization header. Optional + * @return {Object} request + */ + function createRequest(queryString, authHeader) { + var req = request(API_ENDPOINT) + .get(queryString) + .set("Accept", "application/json"); + if (authHeader) { + req = req.set("Authorization", authHeader); + } + return req.expect("Content-Type", /json/); + } + + /** + * Helper method for validating payment list result + * @param {String} queryString - the query string + * @param {String} authHeader - the Authorization header + * @param {String} expectFile - the expect file path + * @param {Function} done - the callback function + */ + function validateResult(queryString, authHeader, expectFile, done) { + createRequest(queryString, authHeader).expect(200).end(function (err, res) { + if (err) { + done(err); + return; + } + var expected = require(expectFile); + delete res.body.serverInformation; + delete res.body.requesterInformation; + assert.deepEqual(res.body, expected, "Invalid response"); + done(); + }); + } + + /** + * Assert error request. + * + * @param {String} queryString - the query string + * @param {String} authHeader - the Authorization header + * @param {Number} statusCode - the expected status code + * @param {String} errorDetail - the error detail. + * @param {Function} done the callback function + */ + function assertError(queryString, authHeader, statusCode, errorDetail, done) { + createRequest(queryString, authHeader).expect(statusCode).end(function (err, res) { + if (err) { + done(err); + return; + } + assert.equal(res.body.error.details, errorDetail, "Invalid error detail"); + done(); + }); + } + + /** + * Test /v2/payments?pageIndex=abc with heffan header + * pageIndex parameter is not number, expect 400 + */ + it("should return error 400 when pageIndex is not number", function (done) { + assertError("/v2/payments?pageIndex=abc", heffanAuthHeader, 400, + "pageIndex should be number.", done); + }); + + /** + * Test /v2/payments?pageIndex=-10 with heffan header + * pageIndex parameter is not positive, expect 400 + */ + it("should return error 400 when pageIndex is not positive", function (done) { + assertError("/v2/payments?pageIndex=-10", heffanAuthHeader, 400, + "pageIndex should be positive.", done); + }); + + /** + * Test /v2/payments?pageIndex=999999999999 with heffan header + * pageIndex parameter is too large, expect 400 + */ + it("should return error 400 when pageIndex is too large", function (done) { + assertError("/v2/payments?pageIndex=999999999999", heffanAuthHeader, 400, + "pageIndex should be less or equal to 2147483647.", done); + }); + + /** + * Test /v2/payments?pageSize=invalid with heffan header + * pageSize parameter is not number, expect 400 + */ + it("should return error 400 when pageSize is not number", function (done) { + assertError("/v2/payments?pageSize=invalid", heffanAuthHeader, 400, + "pageSize should be number.", done); + }); + + /** + * Test /v2/payments?pageSize=999999999999 with heffan header + * pageSize parameter is too large, expect 400 + */ + it("should return error 400 when pageSize is too large", function (done) { + assertError("/v2/payments?pageSize=999999999999", heffanAuthHeader, 400, + "pageSize should be less or equal to 2147483647.", done); + }); + + /** + * Test /v2/payments?pageSize=0 with heffan header + * pageSize parameter is incorrect, expect 400 + */ + it("should return error 400 when pageSize is not positive", function (done) { + assertError("/v2/payments?pageSize=0", heffanAuthHeader, 400, + "pageSize should be positive.", done); + }); + + /** + * Test /v2/payments?sortColumn=invalid with heffan header + * sortColumn parameter is incorrect, expect 400 + */ + it("should return error 400 when sortColumn is incorrect", function (done) { + assertError("/v2/payments?sortColumn=invalid", heffanAuthHeader, 400, + "The sort column 'invalid' is invalid, it should be element of description,type,createDate,releaseDate,paidDate,status,amount.", done); + }); + + /** + * Test /v2/payments?sortOrder=invalid with heffan header + * sortOrder parameter is incorrect, expect 400 + */ + it("should return error 400 when sortOrder is incorrect", function (done) { + assertError("/v2/payments?sortOrder=invalid", heffanAuthHeader, 400, + "sortOrder should be an element of asc,desc.", done); + }); + + /** + * Test /v2/payments without header + * expect 401 when unauthorized error occur + */ + it("should return error 401 when unauthorized error occur", function (done) { + assertError("/v2/payments", null, 401, "Unauthorized Error", done); + }); + + /** + * Test /v2/payments?status=invalid with heffan header + * status parameter is incorrect, expect 400 + */ + it("should return error 400 when status is incorrect", function (done) { + assertError("/v2/payments?status=invalid", heffanAuthHeader, 400, + "The status parameter is incorrect.", done); + }); + + /** + * Test /v2/payments?type= with heffan header + * type parameter is incorrect, expect 400 + */ + it("should return error 400 when type is empty", function (done) { + assertError("/v2/payments?type=", heffanAuthHeader, 400, + "The type parameter should be no-empty string.", done); + }); + + /** + * Test /v2/payments with heffan header + * expect success result + */ + it("should return 10 payments.", function (done) { + validateResult("/v2/payments", heffanAuthHeader, + "./test_files/expected_payment_list_10.json", done); + }); + + /** + * Test /v2/payments?pageSize=20 with heffan header + * expect success result + */ + it("should return 13 payments.", function (done) { + validateResult("/v2/payments?pageSize=20", heffanAuthHeader, + "./test_files/expected_payment_list_13.json", done); + }); + + /** + * Test /v2/payments?type=contest%20payment&sortColumn=paidDate&sortOrder=DESC with heffan header + * expect success result + */ + it("should return 7 payments.", function (done) { + validateResult("/v2/payments?type=contest%20payment&sortColumn=paidDate&sortOrder=DESC", heffanAuthHeader, + "./test_files/expected_payment_list_7.json", done); + }); + + /** + * Test /v2/payments?status=paid&pageSize=3&pageIndex=2 with heffan header + * expect success result + */ + it("should return 2 payments.", function (done) { + validateResult("/v2/payments?status=paid&pageSize=3&pageIndex=2", heffanAuthHeader, + "./test_files/expected_payment_list_2.json", done); + }); + + /** + * Test /v2/payments with user header + * expect success result + */ + it("should return 0 payment.", function (done) { + validateResult("/v2/payments", userAuthHeader, + "./test_files/expected_payment_list_0.json", done); + }); + + /** + * Test /v2/payments?type=invalid with heffan header + * expect success result + */ + it("should return 0 payment when type is not valid.", function (done) { + validateResult("/v2/payments?type=invalid", heffanAuthHeader, + "./test_files/expected_payment_list_heffan_0.json", done); + }); +}); \ No newline at end of file diff --git a/test/test_files/expected_payment_list_0.json b/test/test_files/expected_payment_list_0.json new file mode 100755 index 000000000..61567221e --- /dev/null +++ b/test/test_files/expected_payment_list_0.json @@ -0,0 +1,9 @@ +{ + "total": 0, + "pageIndex": 1, + "pageSize": 10, + "payments": [], + "summary": { + "paid": 0 + } +} \ No newline at end of file diff --git a/test/test_files/expected_payment_list_10.json b/test/test_files/expected_payment_list_10.json new file mode 100755 index 000000000..033fc24e8 --- /dev/null +++ b/test/test_files/expected_payment_list_10.json @@ -0,0 +1,103 @@ +{ + "total": 13, + "pageIndex": 1, + "pageSize": 10, + "payments": [ + { + "description": "contest 2 1st place", + "type": "Contest Payment", + "createDate": "02/18/2014", + "releaseDate": "03/20/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 450 + }, + { + "description": "contest 2 1st place", + "type": "Contest Payment", + "createDate": "02/18/2014", + "releaseDate": "03/20/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 150 + }, + { + "description": "contest 3 1st place", + "type": "Contest Payment", + "createDate": "02/28/2014", + "releaseDate": "03/30/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 600 + }, + { + "description": "contest 3 1st place", + "type": "Contest Payment", + "createDate": "02/28/2014", + "releaseDate": "03/30/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 200 + }, + { + "description": "contest 4 2nd place", + "type": "Contest Payment", + "createDate": "02/28/2014", + "releaseDate": "04/04/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 500 + }, + { + "description": "contest 1 1st place", + "type": "Contest Payment", + "createDate": "03/20/2014", + "releaseDate": "04/19/2014", + "paidDate": "", + "status": "Owed", + "amount": 300 + }, + { + "description": "contest 1 1st place", + "type": "Contest Payment", + "createDate": "03/20/2014", + "releaseDate": "04/19/2014", + "paidDate": "", + "status": "Owed", + "amount": 100 + }, + { + "description": "2014 February Development Track Top Performers 10th place", + "type": "Digital Run v2 Top Performers Payment", + "createDate": "03/22/2014", + "releaseDate": "04/06/2014", + "paidDate": "", + "status": "Entered into payment system", + "amount": 435.24 + }, + { + "description": "2014 February Development Track Top Performers 10th place (taxable)", + "type": "Digital Run v2 Top Performers Payment (taxable)", + "createDate": "03/22/2014", + "releaseDate": "04/06/2014", + "paidDate": "", + "status": "Entered into payment system", + "amount": 20.15 + }, + { + "description": "component 1 1st place(1st installment, total amount=400.00)", + "type": "Component Payment", + "createDate": "03/30/2014", + "releaseDate": "04/29/2014", + "paidDate": "", + "status": "Owed", + "amount": 250 + } + ], + "summary": { + "paid": 1900, + "owed": 800, + "enteredIntoPaymentSystem": 455.39, + "accruing": 275 + } +} \ No newline at end of file diff --git a/test/test_files/expected_payment_list_13.json b/test/test_files/expected_payment_list_13.json new file mode 100755 index 000000000..5deee7fa5 --- /dev/null +++ b/test/test_files/expected_payment_list_13.json @@ -0,0 +1,130 @@ +{ + "total": 13, + "pageIndex": 1, + "pageSize": 20, + "payments": [ + { + "description": "contest 2 1st place", + "type": "Contest Payment", + "createDate": "02/18/2014", + "releaseDate": "03/20/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 450 + }, + { + "description": "contest 2 1st place", + "type": "Contest Payment", + "createDate": "02/18/2014", + "releaseDate": "03/20/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 150 + }, + { + "description": "contest 3 1st place", + "type": "Contest Payment", + "createDate": "02/28/2014", + "releaseDate": "03/30/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 600 + }, + { + "description": "contest 3 1st place", + "type": "Contest Payment", + "createDate": "02/28/2014", + "releaseDate": "03/30/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 200 + }, + { + "description": "contest 4 2nd place", + "type": "Contest Payment", + "createDate": "02/28/2014", + "releaseDate": "04/04/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 500 + }, + { + "description": "contest 1 1st place", + "type": "Contest Payment", + "createDate": "03/20/2014", + "releaseDate": "04/19/2014", + "paidDate": "", + "status": "Owed", + "amount": 300 + }, + { + "description": "contest 1 1st place", + "type": "Contest Payment", + "createDate": "03/20/2014", + "releaseDate": "04/19/2014", + "paidDate": "", + "status": "Owed", + "amount": 100 + }, + { + "description": "2014 February Development Track Top Performers 10th place", + "type": "Digital Run v2 Top Performers Payment", + "createDate": "03/22/2014", + "releaseDate": "04/06/2014", + "paidDate": "", + "status": "Entered into payment system", + "amount": 435.24 + }, + { + "description": "2014 February Development Track Top Performers 10th place (taxable)", + "type": "Digital Run v2 Top Performers Payment (taxable)", + "createDate": "03/22/2014", + "releaseDate": "04/06/2014", + "paidDate": "", + "status": "Entered into payment system", + "amount": 20.15 + }, + { + "description": "component 1 1st place(1st installment, total amount=400.00)", + "type": "Component Payment", + "createDate": "03/30/2014", + "releaseDate": "04/29/2014", + "paidDate": "", + "status": "Owed", + "amount": 250 + }, + { + "description": "component 1 1st place(2nd installment, total amount=400.00)", + "type": "Component Payment", + "createDate": "03/30/2014", + "releaseDate": "04/29/2014", + "paidDate": "", + "status": "Owed", + "amount": 150 + }, + { + "description": "contest review 1", + "type": "Review Board Payment", + "createDate": "04/09/2014", + "releaseDate": "05/09/2014", + "paidDate": "", + "status": "Accruing", + "amount": 225 + }, + { + "description": "spec review 1", + "type": "Specification Review Payment", + "createDate": "04/09/2014", + "releaseDate": "05/09/2014", + "paidDate": "", + "status": "Accruing", + "amount": 50 + } + ], + "summary": { + "paid": 1900, + "owed": 800, + "enteredIntoPaymentSystem": 455.39, + "accruing": 275 + } +} \ No newline at end of file diff --git a/test/test_files/expected_payment_list_2.json b/test/test_files/expected_payment_list_2.json new file mode 100755 index 000000000..0446fabf3 --- /dev/null +++ b/test/test_files/expected_payment_list_2.json @@ -0,0 +1,31 @@ +{ + "total": 5, + "pageIndex": 2, + "pageSize": 3, + "payments": [ + { + "description": "contest 3 1st place", + "type": "Contest Payment", + "createDate": "02/28/2014", + "releaseDate": "03/30/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 200 + }, + { + "description": "contest 4 2nd place", + "type": "Contest Payment", + "createDate": "02/28/2014", + "releaseDate": "04/04/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 500 + } + ], + "summary": { + "paid": 1900, + "owed": 800, + "enteredIntoPaymentSystem": 455.39, + "accruing": 275 + } +} \ No newline at end of file diff --git a/test/test_files/expected_payment_list_7.json b/test/test_files/expected_payment_list_7.json new file mode 100755 index 000000000..b98f81df3 --- /dev/null +++ b/test/test_files/expected_payment_list_7.json @@ -0,0 +1,76 @@ +{ + "total": 7, + "pageIndex": 1, + "pageSize": 10, + "payments": [ + { + "description": "contest 4 2nd place", + "type": "Contest Payment", + "createDate": "02/28/2014", + "releaseDate": "04/04/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 500 + }, + { + "description": "contest 3 1st place", + "type": "Contest Payment", + "createDate": "02/28/2014", + "releaseDate": "03/30/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 200 + }, + { + "description": "contest 3 1st place", + "type": "Contest Payment", + "createDate": "02/28/2014", + "releaseDate": "03/30/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 600 + }, + { + "description": "contest 2 1st place", + "type": "Contest Payment", + "createDate": "02/18/2014", + "releaseDate": "03/20/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 150 + }, + { + "description": "contest 2 1st place", + "type": "Contest Payment", + "createDate": "02/18/2014", + "releaseDate": "03/20/2014", + "paidDate": "04/08/2014", + "status": "Paid", + "amount": 450 + }, + { + "description": "contest 1 1st place", + "type": "Contest Payment", + "createDate": "03/20/2014", + "releaseDate": "04/19/2014", + "paidDate": "", + "status": "Owed", + "amount": 300 + }, + { + "description": "contest 1 1st place", + "type": "Contest Payment", + "createDate": "03/20/2014", + "releaseDate": "04/19/2014", + "paidDate": "", + "status": "Owed", + "amount": 100 + } + ], + "summary": { + "paid": 1900, + "owed": 800, + "enteredIntoPaymentSystem": 455.39, + "accruing": 275 + } +} \ No newline at end of file diff --git a/test/test_files/expected_payment_list_heffan_0.json b/test/test_files/expected_payment_list_heffan_0.json new file mode 100755 index 000000000..bcaadbaab --- /dev/null +++ b/test/test_files/expected_payment_list_heffan_0.json @@ -0,0 +1,12 @@ +{ + "total": 0, + "pageIndex": 1, + "pageSize": 10, + "payments": [], + "summary": { + "paid": 1900, + "owed": 800, + "enteredIntoPaymentSystem": 455.39, + "accruing": 275 + } +} \ No newline at end of file