From a079463520d7955c8a64c1baf12ae79045a9fbb4 Mon Sep 17 00:00:00 2001 From: Pavlo Vodopyan Date: Sat, 13 May 2017 17:14:29 +0100 Subject: [PATCH 1/5] Cancel new leave request without approving. --- lib/email.js | 58 +++++++++++++++++++ lib/model/db/leave.js | 17 ++++++ lib/model/mixin/user/absence_aware.js | 22 ++++++- lib/route/requests.js | 54 +++++++++++++++++ .../leave_request_cancel_to_requestor.hbs | 7 +++ .../leave_request_cancel_to_supervisor.hbs | 9 +++ views/partials/user_requests.hbs | 5 ++ 7 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 views/email/leave_request_cancel_to_requestor.hbs create mode 100644 views/email/leave_request_cancel_to_supervisor.hbs diff --git a/lib/email.js b/lib/email.js index 8368a9de9..18009da2c 100644 --- a/lib/email.js +++ b/lib/email.js @@ -397,5 +397,63 @@ Email.prototype.promise_reset_password_email = function(args){ }); }; +Email.prototype.promise_leave_request_cancel_emails = function(args){ + var self = this, + leave = args.leave, + send_mail = self.get_send_email(); + + var promise_email_to_supervisor = self.promise_rendered_email_template({ + template_name : 'leave_request_cancel_to_supervisor', + context : { + leave : leave, + approver : leave.get('approver'), + requester : leave.get('user'), + user : leave.get('approver'), + } + }) + .then(function(email_obj){ + + return send_mail({ + from : config.get('application_sender_email'), + to : leave.get('approver').email, + subject : email_obj.subject, + html : email_obj.body, + }) + .then(function(send_result){ + return leave.get('approver').record_email_addressed_to_me(email_obj) + .then(function(){ return bluebird.resolve( send_result ); }); + }); + }); + + var promise_email_to_requestor = self.promise_rendered_email_template({ + template_name : 'leave_request_cancel_to_requestor', + context : { + leave : leave, + approver : leave.get('approver'), + requester : leave.get('user'), + user : leave.get('user'), + } + }) + .then(function(email_obj){ + + return send_mail({ + from : config.get('application_sender_email'), + to : leave.get('user').email, + subject : email_obj.subject, + html : email_obj.body, + }) + .then(function(send_result){ + return leave.get('user').record_email_addressed_to_me(email_obj) + .then(function(){ return bluebird.resolve( send_result ); }); + }); + }); + + return bluebird.join( + promise_email_to_supervisor, promise_email_to_requestor, + function(){ + return bluebird.resolve(); + } + ); +}; module.exports = Email; diff --git a/lib/model/db/leave.js b/lib/model/db/leave.js index 4c49888ad..9b491f982 100644 --- a/lib/model/db/leave.js +++ b/lib/model/db/leave.js @@ -83,6 +83,10 @@ module.exports = function(sequelize, DataTypes) { return 4; }, + status_canceled : function() { + return 5; + }, + leave_day_part_all : function(){ return 1; @@ -381,6 +385,18 @@ promise_to_revoke : function(){ }) }, +promise_to_cancel : function(){ + var self = this; + + if ( ! self.is_new_leave() ) { + throw new Error('An attempt to cancel non-new leave request id : '+self.id); + } + + self.status = Leave.status_canceled(); + + return self.save(); +}, + get_leave_type_name : function() { var leave_type = this.get('leave_type'); @@ -405,6 +421,7 @@ promise_approver : function() { }) }, + }, }); diff --git a/lib/model/mixin/user/absence_aware.js b/lib/model/mixin/user/absence_aware.js index 362da704e..288369c6f 100644 --- a/lib/model/mixin/user/absence_aware.js +++ b/lib/model/mixin/user/absence_aware.js @@ -134,7 +134,10 @@ module.exports = function(sequelize){ return this_user.getMy_leaves({ where : { - status : { $ne : sequelize.models.Leave.status_rejected()}, + $and : [ + { status : { $ne : sequelize.models.Leave.status_rejected() } }, + { status : { $ne : sequelize.models.Leave.status_canceled() } }, + ], $or : { date_start : days_filter, @@ -309,6 +312,23 @@ module.exports = function(sequelize){ }); }; // END of promise_leaves_to_be_processed + this.promise_cancelable_leaves = function(){ + var self = this; + + return self.promise_my_leaves({ + ignore_year : true, + filter_status : [ sequelize.models.Leave.status_new() ], + }) + .then(function(leaves){ + return Promise.map(leaves, function(leave){ + return leave.user.promise_schedule_I_obey(); + },{ + concurrency : 10, + }) + .then(function(){ return Promise.resolve(leaves) }); + }); + }; + this.calculate_number_of_days_taken_from_allowance = function(args){ var self = this, diff --git a/lib/route/requests.js b/lib/route/requests.js index 2783ee78f..ce5c9eb91 100644 --- a/lib/route/requests.js +++ b/lib/route/requests.js @@ -119,6 +119,60 @@ router.post( }) ); +router.post('/cancel/', function(req, res){ + + var request_id = validator.trim( req.param('request') ); + + Promise.try(function(){ + return req.user.promise_cancelable_leaves() + }) + .then(function(leaves){ + var leave_to_cancel = _.find(leaves, function(leave){ + return String(leave.id) === String(request_id); + }); + + if ( ! leave_to_cancel ) { + throw new Error('Given leave request is not amoung those current user can cancel'); + } + + return Promise.resolve(leave_to_cancel); + }) + .then(function(leave){ + return leave.promise_to_cancel() + .then(function(){ return Promise.resolve(leave)}); + }) + .then(function(leave){ + return leave.reload({ + include : [ + {model : req.app.get('db_model').User, as : 'user'}, + {model : req.app.get('db_model').User, as : 'approver'}, + {model : req.app.get('db_model').LeaveType, as : 'leave_type' }, + ], + }); + }) + .then(function(leave){ + + var Email = new EmailTransport(); + + return Email.promise_leave_request_cancel_emails({ + leave : leave, + }) + .then(function(){ + return Promise.resolve(leave); + }); + }) + .then(function(leave){ + req.session.flash_message('The leave request was canceled'); + }) + .catch(function(error){ + console.log('An error occurred: '+error); + req.session.flash_error('Failed to cancel leave request'); + }) + .finally(function(){ + return res.redirect_with_session('/requests/'); + }); +}); + router.post( '/revoke/', function(req, res){ diff --git a/views/email/leave_request_cancel_to_requestor.hbs b/views/email/leave_request_cancel_to_requestor.hbs new file mode 100644 index 000000000..4fe6fba7e --- /dev/null +++ b/views/email/leave_request_cancel_to_requestor.hbs @@ -0,0 +1,7 @@ +Leave request was cancelled +===== +

Hello {{#with requester}}{{this.full_name}}{{/with}},

+ +

Your leave request {{>leave_request_detail leave=leave }} was cancelled.

+ +

Thanks

diff --git a/views/email/leave_request_cancel_to_supervisor.hbs b/views/email/leave_request_cancel_to_supervisor.hbs new file mode 100644 index 000000000..6016c1b4a --- /dev/null +++ b/views/email/leave_request_cancel_to_supervisor.hbs @@ -0,0 +1,9 @@ +Cancel leave request +===== +

Hello {{#with approver }}{{this.full_name}}{{/with}},

+ +

{{#with requester}}{{this.full_name}}{{/with}} cancelled leave request {{>leave_request_detail leave=leave }}.

+ +

No actions are needed.

+ +

Thanks

diff --git a/views/partials/user_requests.hbs b/views/partials/user_requests.hbs index 79c6a4ae3..b88f15277 100644 --- a/views/partials/user_requests.hbs +++ b/views/partials/user_requests.hbs @@ -43,6 +43,11 @@ {{/unless}} + {{else}} +
+ + +
{{/if}} {{#if this.is_new_leave }}Pending{{else}}{{#if this.is_approved_leave}}Approved{{else}}Rejected{{/if}}{{/if}} From ceab83f3f6b511b74a0edbe0d9d4e7b9e03c2639 Mon Sep 17 00:00:00 2001 From: Pavlo Vodopyan Date: Tue, 16 May 2017 16:34:26 +0100 Subject: [PATCH 2/5] Group tests for leave requests --- .../{ => leave_request}/basic_leave_request.js | 18 +++++++++--------- .../book_leave_request_form.js | 18 +++++++++--------- .../create_leave_with_single_user.js | 14 +++++++------- .../leave_request_revoke.js | 18 +++++++++--------- .../leave_request_revoke_by_admin.js | 18 +++++++++--------- .../{ => leave_request}/ovelapping_bookings.js | 18 +++++++++--------- .../ovelapping_bookings_halfs.js | 18 +++++++++--------- .../request_leaves_for_other_users.js | 14 +++++++------- .../try_to_overbook_allowance.js | 18 +++++++++--------- 9 files changed, 77 insertions(+), 77 deletions(-) rename t/integration/{ => leave_request}/basic_leave_request.js (93%) rename t/integration/{ => leave_request}/book_leave_request_form.js (85%) rename t/integration/{ => leave_request}/create_leave_with_single_user.js (85%) rename t/integration/{ => leave_request}/leave_request_revoke.js (94%) rename t/integration/{ => leave_request}/leave_request_revoke_by_admin.js (92%) rename t/integration/{ => leave_request}/ovelapping_bookings.js (87%) rename t/integration/{ => leave_request}/ovelapping_bookings_halfs.js (92%) rename t/integration/{ => leave_request}/request_leaves_for_other_users.js (95%) rename t/integration/{ => leave_request}/try_to_overbook_allowance.js (87%) diff --git a/t/integration/basic_leave_request.js b/t/integration/leave_request/basic_leave_request.js similarity index 93% rename from t/integration/basic_leave_request.js rename to t/integration/leave_request/basic_leave_request.js index 2e0ceec0e..756ad7bf3 100644 --- a/t/integration/basic_leave_request.js +++ b/t/integration/leave_request/basic_leave_request.js @@ -2,7 +2,7 @@ 'use strict'; var test = require('selenium-webdriver/testing'), - config = require('../lib/config'), + config = require('../../lib/config'), application_host = config.get_application_host(), By = require('selenium-webdriver').By, expect = require('chai').expect, @@ -10,14 +10,14 @@ var test = require('selenium-webdriver/testing'), Promise = require("bluebird"), moment = require('moment'), until = require('selenium-webdriver').until, - login_user_func = require('../lib/login_with_user'), - register_new_user_func = require('../lib/register_new_user'), - logout_user_func = require('../lib/logout_user'), - open_page_func = require('../lib/open_page'), - submit_form_func = require('../lib/submit_form'), - check_elements_func = require('../lib/check_elements'), - check_booking_func = require('../lib/check_booking_on_calendar'), - add_new_user_func = require('../lib/add_new_user'); + login_user_func = require('../../lib/login_with_user'), + register_new_user_func = require('../../lib/register_new_user'), + logout_user_func = require('../../lib/logout_user'), + open_page_func = require('../../lib/open_page'), + submit_form_func = require('../../lib/submit_form'), + check_elements_func = require('../../lib/check_elements'), + check_booking_func = require('../../lib/check_booking_on_calendar'), + add_new_user_func = require('../../lib/add_new_user'); /* diff --git a/t/integration/book_leave_request_form.js b/t/integration/leave_request/book_leave_request_form.js similarity index 85% rename from t/integration/book_leave_request_form.js rename to t/integration/leave_request/book_leave_request_form.js index aa0fedb94..168f5af93 100644 --- a/t/integration/book_leave_request_form.js +++ b/t/integration/leave_request/book_leave_request_form.js @@ -2,7 +2,7 @@ 'use strict'; var test = require('selenium-webdriver/testing'), - config = require('../lib/config'), + config = require('../../lib/config'), application_host = config.get_application_host(), By = require('selenium-webdriver').By, expect = require('chai').expect, @@ -10,14 +10,14 @@ var test = require('selenium-webdriver/testing'), Promise = require("bluebird"), moment = require('moment'), until = require('selenium-webdriver').until, - login_user_func = require('../lib/login_with_user'), - register_new_user_func = require('../lib/register_new_user'), - logout_user_func = require('../lib/logout_user'), - open_page_func = require('../lib/open_page'), - submit_form_func = require('../lib/submit_form'), - check_elements_func = require('../lib/check_elements'), - check_booking_func = require('../lib/check_booking_on_calendar'), - add_new_user_func = require('../lib/add_new_user'); + login_user_func = require('../../lib/login_with_user'), + register_new_user_func = require('../../lib/register_new_user'), + logout_user_func = require('../../lib/logout_user'), + open_page_func = require('../../lib/open_page'), + submit_form_func = require('../../lib/submit_form'), + check_elements_func = require('../../lib/check_elements'), + check_booking_func = require('../../lib/check_booking_on_calendar'), + add_new_user_func = require('../../lib/add_new_user'); describe("Check the client side logic to facilitate filling new absence form", function(){ diff --git a/t/integration/create_leave_with_single_user.js b/t/integration/leave_request/create_leave_with_single_user.js similarity index 85% rename from t/integration/create_leave_with_single_user.js rename to t/integration/leave_request/create_leave_with_single_user.js index 5f4f186b9..75ed05219 100644 --- a/t/integration/create_leave_with_single_user.js +++ b/t/integration/leave_request/create_leave_with_single_user.js @@ -2,19 +2,19 @@ 'use strict'; var test = require('selenium-webdriver/testing'), - config = require('../lib/config'), + config = require('../../lib/config'), application_host = config.get_application_host(), By = require('selenium-webdriver').By, expect = require('chai').expect, _ = require('underscore'), Promise = require("bluebird"), moment = require('moment'), - login_user_func = require('../lib/login_with_user'), - register_new_user_func = require('../lib/register_new_user'), - open_page_func = require('../lib/open_page'), - submit_form_func = require('../lib/submit_form'), - check_elements_func = require('../lib/check_elements'), - check_booking_func = require('../lib/check_booking_on_calendar'); + login_user_func = require('../../lib/login_with_user'), + register_new_user_func = require('../../lib/register_new_user'), + open_page_func = require('../../lib/open_page'), + submit_form_func = require('../../lib/submit_form'), + check_elements_func = require('../../lib/check_elements'), + check_booking_func = require('../../lib/check_booking_on_calendar'); /* diff --git a/t/integration/leave_request_revoke.js b/t/integration/leave_request/leave_request_revoke.js similarity index 94% rename from t/integration/leave_request_revoke.js rename to t/integration/leave_request/leave_request_revoke.js index 710ed9fa7..b1da6dae7 100644 --- a/t/integration/leave_request_revoke.js +++ b/t/integration/leave_request/leave_request_revoke.js @@ -8,15 +8,15 @@ var test = require('selenium-webdriver/testing'), moment = require('moment'), Promise = require("bluebird"), until = require('selenium-webdriver').until, - register_new_user_func = require('../lib/register_new_user'), - login_user_func = require('../lib/login_with_user'), - open_page_func = require('../lib/open_page'), - submit_form_func = require('../lib/submit_form'), - add_new_user_func = require('../lib/add_new_user'), - logout_user_func = require('../lib/logout_user'), - check_booking_func = require('../lib/check_booking_on_calendar'), - check_elements_func = require('../lib/check_elements'), - config = require('../lib/config'), + register_new_user_func = require('../../lib/register_new_user'), + login_user_func = require('../../lib/login_with_user'), + open_page_func = require('../../lib/open_page'), + submit_form_func = require('../../lib/submit_form'), + add_new_user_func = require('../../lib/add_new_user'), + logout_user_func = require('../../lib/logout_user'), + check_booking_func = require('../../lib/check_booking_on_calendar'), + check_elements_func = require('../../lib/check_elements'), + config = require('../../lib/config'), application_host = config.get_application_host(); /* diff --git a/t/integration/leave_request_revoke_by_admin.js b/t/integration/leave_request/leave_request_revoke_by_admin.js similarity index 92% rename from t/integration/leave_request_revoke_by_admin.js rename to t/integration/leave_request/leave_request_revoke_by_admin.js index 53d979e68..baee4d4f3 100644 --- a/t/integration/leave_request_revoke_by_admin.js +++ b/t/integration/leave_request/leave_request_revoke_by_admin.js @@ -8,15 +8,15 @@ var test = require('selenium-webdriver/testing'), Promise = require("bluebird"), moment = require('moment'), until = require('selenium-webdriver').until, - login_user_func = require('../lib/login_with_user'), - register_new_user_func = require('../lib/register_new_user'), - logout_user_func = require('../lib/logout_user'), - open_page_func = require('../lib/open_page'), - submit_form_func = require('../lib/submit_form'), - check_elements_func = require('../lib/check_elements'), - check_booking_func = require('../lib/check_booking_on_calendar'), - add_new_user_func = require('../lib/add_new_user'), - config = require('../lib/config'), + login_user_func = require('../../lib/login_with_user'), + register_new_user_func = require('../../lib/register_new_user'), + logout_user_func = require('../../lib/logout_user'), + open_page_func = require('../../lib/open_page'), + submit_form_func = require('../../lib/submit_form'), + check_elements_func = require('../../lib/check_elements'), + check_booking_func = require('../../lib/check_booking_on_calendar'), + add_new_user_func = require('../../lib/add_new_user'), + config = require('../../lib/config'), application_host = config.get_application_host(); /* diff --git a/t/integration/ovelapping_bookings.js b/t/integration/leave_request/ovelapping_bookings.js similarity index 87% rename from t/integration/ovelapping_bookings.js rename to t/integration/leave_request/ovelapping_bookings.js index 2edb9b4b4..df96ee40f 100644 --- a/t/integration/ovelapping_bookings.js +++ b/t/integration/leave_request/ovelapping_bookings.js @@ -8,15 +8,15 @@ var test = require('selenium-webdriver/testing'), _ = require('underscore'), Promise = require("bluebird"), moment = require('moment'), - login_user_func = require('../lib/login_with_user'), - register_new_user_func = require('../lib/register_new_user'), - logout_user_func = require('../lib/logout_user'), - open_page_func = require('../lib/open_page'), - submit_form_func = require('../lib/submit_form'), - check_elements_func = require('../lib/check_elements'), - check_booking_func = require('../lib/check_booking_on_calendar'), - add_new_user_func = require('../lib/add_new_user'), - config = require('../lib/config'), + login_user_func = require('../../lib/login_with_user'), + register_new_user_func = require('../../lib/register_new_user'), + logout_user_func = require('../../lib/logout_user'), + open_page_func = require('../../lib/open_page'), + submit_form_func = require('../../lib/submit_form'), + check_elements_func = require('../../lib/check_elements'), + check_booking_func = require('../../lib/check_booking_on_calendar'), + add_new_user_func = require('../../lib/add_new_user'), + config = require('../../lib/config'), application_host = config.get_application_host(); /* diff --git a/t/integration/ovelapping_bookings_halfs.js b/t/integration/leave_request/ovelapping_bookings_halfs.js similarity index 92% rename from t/integration/ovelapping_bookings_halfs.js rename to t/integration/leave_request/ovelapping_bookings_halfs.js index 712196df4..520d4101e 100644 --- a/t/integration/ovelapping_bookings_halfs.js +++ b/t/integration/leave_request/ovelapping_bookings_halfs.js @@ -8,16 +8,16 @@ var test = require('selenium-webdriver/testing'), _ = require('underscore'), Promise = require("bluebird"), moment = require('moment'), - config = require('../lib/config'), + config = require('../../lib/config'), application_host = config.get_application_host(), - login_user_func = require('../lib/login_with_user'), - register_new_user_func = require('../lib/register_new_user'), - logout_user_func = require('../lib/logout_user'), - open_page_func = require('../lib/open_page'), - submit_form_func = require('../lib/submit_form'), - check_elements_func = require('../lib/check_elements'), - check_booking_func = require('../lib/check_booking_on_calendar'), - add_new_user_func = require('../lib/add_new_user'); + login_user_func = require('../../lib/login_with_user'), + register_new_user_func = require('../../lib/register_new_user'), + logout_user_func = require('../../lib/logout_user'), + open_page_func = require('../../lib/open_page'), + submit_form_func = require('../../lib/submit_form'), + check_elements_func = require('../../lib/check_elements'), + check_booking_func = require('../../lib/check_booking_on_calendar'), + add_new_user_func = require('../../lib/add_new_user'); /* * Scenario to go in this test: diff --git a/t/integration/request_leaves_for_other_users.js b/t/integration/leave_request/request_leaves_for_other_users.js similarity index 95% rename from t/integration/request_leaves_for_other_users.js rename to t/integration/leave_request/request_leaves_for_other_users.js index 81dc856b8..fc0b66435 100644 --- a/t/integration/request_leaves_for_other_users.js +++ b/t/integration/leave_request/request_leaves_for_other_users.js @@ -2,19 +2,19 @@ 'use strict'; var test = require('selenium-webdriver/testing'), - config = require('../lib/config'), + config = require('../../lib/config'), application_host = config.get_application_host(), By = require('selenium-webdriver').By, expect = require('chai').expect, _ = require('underscore'), Promise = require("bluebird"), until = require('selenium-webdriver').until, - login_user_func = require('../lib/login_with_user'), - register_new_user_func = require('../lib/register_new_user'), - logout_user_func = require('../lib/logout_user'), - open_page_func = require('../lib/open_page'), - submit_form_func = require('../lib/submit_form'), - add_new_user_func = require('../lib/add_new_user'), + login_user_func = require('../../lib/login_with_user'), + register_new_user_func = require('../../lib/register_new_user'), + logout_user_func = require('../../lib/logout_user'), + open_page_func = require('../../lib/open_page'), + submit_form_func = require('../../lib/submit_form'), + add_new_user_func = require('../../lib/add_new_user'), new_department_form_id = '#add_new_department_form'; /* diff --git a/t/integration/try_to_overbook_allowance.js b/t/integration/leave_request/try_to_overbook_allowance.js similarity index 87% rename from t/integration/try_to_overbook_allowance.js rename to t/integration/leave_request/try_to_overbook_allowance.js index d444aeda2..fdc13a1de 100644 --- a/t/integration/try_to_overbook_allowance.js +++ b/t/integration/leave_request/try_to_overbook_allowance.js @@ -2,21 +2,21 @@ 'use strict'; var test = require('selenium-webdriver/testing'), - config = require('../lib/config'), + config = require('../../lib/config'), application_host = config.get_application_host(), By = require('selenium-webdriver').By, expect = require('chai').expect, _ = require('underscore'), Promise = require("bluebird"), until = require('selenium-webdriver').until, - login_user_func = require('../lib/login_with_user'), - register_new_user_func = require('../lib/register_new_user'), - logout_user_func = require('../lib/logout_user'), - open_page_func = require('../lib/open_page'), - submit_form_func = require('../lib/submit_form'), - check_elements_func = require('../lib/check_elements'), - check_booking_func = require('../lib/check_booking_on_calendar'), - add_new_user_func = require('../lib/add_new_user'); + login_user_func = require('../../lib/login_with_user'), + register_new_user_func = require('../../lib/register_new_user'), + logout_user_func = require('../../lib/logout_user'), + open_page_func = require('../../lib/open_page'), + submit_form_func = require('../../lib/submit_form'), + check_elements_func = require('../../lib/check_elements'), + check_booking_func = require('../../lib/check_booking_on_calendar'), + add_new_user_func = require('../../lib/add_new_user'); /* From 95c63f69bc215063ad29807c012d367d13aeb596 Mon Sep 17 00:00:00 2001 From: Pavlo Vodopyan Date: Thu, 18 May 2017 08:23:35 +0100 Subject: [PATCH 3/5] Add test for request cancelation. --- t/integration/leave_request/cancel_basic.js | 339 ++++++++++++++++++++ views/audit/emails.hbs | 2 +- views/partials/user_requests.hbs | 6 +- 3 files changed, 343 insertions(+), 4 deletions(-) create mode 100644 t/integration/leave_request/cancel_basic.js diff --git a/t/integration/leave_request/cancel_basic.js b/t/integration/leave_request/cancel_basic.js new file mode 100644 index 000000000..2665c0aac --- /dev/null +++ b/t/integration/leave_request/cancel_basic.js @@ -0,0 +1,339 @@ + +'use strict'; + +var test = require('selenium-webdriver/testing'), + By = require('selenium-webdriver').By, + until = require('selenium-webdriver').until, + Promise = require("bluebird"), + expect = require('chai').expect, + add_new_user_func = require('../../lib/add_new_user'), + check_elements_func = require('../../lib/check_elements'), + config = require('../../lib/config'), + login_user_func = require('../../lib/login_with_user'), + logout_user_func = require('../../lib/logout_user'), + open_page_func = require('../../lib/open_page'), + register_new_user_func = require('../../lib/register_new_user'), + submit_form_func = require('../../lib/submit_form'), + user_info_func = require('../../lib/user_info'), + application_host = config.get_application_host(), + some_weekday_date = '2015-06-17'; + +/* + * Scenario: + * * Create a company with admin user A and regular employee B + * * Login as regular user B and place a leave request + * * Go to Requests page and ensure that new entry apeared in My leaves section + * * New entry is in Pending status and has Delete/Cancel icon + * * Cancel leave request + * * Ensure that My requests page does not contain any entries + * * Login as admin user A and ensure that there is no pending leave requests + * * Go to email audit page and ensure that there were two emails regarding cancelation + * * Go to user B details and ensure its details shows nothing from allowance was used + * * Login back as user B + * * Submit leave request for the same date as the first one was + * * Ensure it is successful and apperes as Pending + * + * */ + +describe('Leave request cancelation', function(){ + + this.timeout( config.get_execution_timeout() ); + + var driver, email_A, email_B, user_id_A, user_id_B; + + it("Register new company", function(done){ + register_new_user_func({ + application_host : application_host, + }) + .then(function(data){ + driver = data.driver; + email_A = data.email; + done(); + }); + }); + + it("Create second user B", function(done){ + add_new_user_func({ + application_host : application_host, + driver : driver, + }) + .then(function(data){ + email_B = data.new_user_email; + done(); + }); + }); + + it("Obtain information about admin user A", function(done){ + user_info_func({ + driver : driver, + email : email_A, + }) + .then(function(data){ + user_id_A = data.user.id; + done(); + }); + }); + + it("Obtain information about user B", function(done){ + user_info_func({ + driver : driver, + email : email_B, + }) + .then(function(data){ + user_id_B = data.user.id; + done(); + }); + }); + + it("Logout from user A (admin)", function(done){ + logout_user_func({ + application_host : application_host, + driver : driver, + }) + .then(function(){ done() }); + }); + + it("Login as user B", function(done){ + login_user_func({ + application_host : application_host, + user_email : email_B, + driver : driver, + }) + .then(function(){ done() }); + }); + + it("Open Book leave popup window", function(done){ + driver.findElement(By.css('#book_time_off_btn')) + .then(function(el){ return el.click() }) + .then(function(el){ + // This is very important line when working with Bootstrap modals! + return driver.sleep(1000); + }) + .then(function(){ done() }); + }); + + it("Submit new leave requesti from user B for one weekday", function(done){ + submit_form_func({ + driver : driver, + form_params : [{ + selector : 'input#from', + value : some_weekday_date, + },{ + selector : 'input#to', + value : some_weekday_date, + }], + message : /New leave request was added/, + }) + .then(function(){done()}); + }); + + it("Open requests page", function( done ){ + open_page_func({ + url : application_host + 'requests/', + driver : driver, + }) + .then(function(){ done() }); + }); + + it('Ensure newly created request is on Requests page', function(done){ + check_elements_func({ + driver : driver, + elements_to_check : [{ + selector : 'tr.leave-request-row form[action="/requests/cancel/"] button[type="submit"]', + value : "cancel", + }], + }) + .then(function(){ done() }); + }); + + it('Ensure that new request is single one', function(done){ + driver + .findElements(By.css( 'tr.leave-request-row' )) + .then(function(elements){ + expect( elements.length ).to.be.eq(1); + done(); + }) + }); + + it('Ensure that new request is in Pending status', function(done){ + driver + .findElement(By.css( 'tr.leave-request-row .leave-request-row-status' )) + .then(function(element){ + return element.getText(); + }) + .then(function(status){ + expect( status ).to.be.eq('Pending'); + done(); + }); + }); + + it("Cancel leave request", function(done){ + driver + .findElement(By.css( + 'tr.leave-request-row form[action="/requests/cancel/"] button[type="submit"]' + )) + .then(function(cancel_btn){ + return cancel_btn.click(); + }) + .then(function(){ + // Wait until page properly is reloaded + return driver.wait(until.elementLocated(By.css('h1')), 1000); + }) + .then(function(){ done() }); + }); + + it('Ensure that My requests page does not contain any entries', function(done){ + driver + .findElements(By.css( 'tr.leave-request-row' )) + .then(function(elements){ + expect( elements.length ).to.be.eq(0); + done(); + }) + }); + + it(" Logout from user B account", function(done){ + logout_user_func({ + application_host : application_host, + driver : driver, + }) + .then(function(){ done() }); + }); + + it("Login back as admin user A", function(done){ + login_user_func({ + application_host : application_host, + user_email : email_A, + driver : driver, + }) + .then(function(){ done() }); + }); + + it("Open requests page", function( done ){ + open_page_func({ + url : application_host + 'requests/', + driver : driver, + }) + .then(function(){ done() }); + }); + + it('Ensure that there is no pending leave requests', function(done){ + driver + .findElements(By.css( '.btn-warning' )) + .then(function(elements){ + expect( elements.length ).to.be.eq(0); + done(); + }) + }); + + it("Open email audit page", function( done ){ + open_page_func({ + url : application_host + 'audit/email/', + driver : driver, + }) + .then(function(){ done() }); + }); + + it('Ensure that there were two emails regarding cancelation', function(done){ + driver + .findElements( By.css('tr.vpp-email-audit-entry-header a.collapsed') ) + .then(function(elements){ + return Promise.map( + [elements[0], elements[1]], + function(el){ return el.getText() } + ); + }) + .then(function(subjects){ + expect(subjects).to.contain('Leave request was cancelled'); + expect(subjects).to.contain('Cancel leave request'); + done(); + }) + }); + + it('Open user B absences section', function(done){ + open_page_func({ + url : application_host + 'users/edit/'+user_id_B+'/absences/', + driver : driver, + }) + .then(function(){ done() }); + }); + + it('Ensure its details shows nothing from allowance was used', function(done){ + driver + .findElement( By.css('#days_remaining_inp') ) + .then(function(inp){ + return inp.getAttribute('value'); + }) + .then(function(text){ + // It says XX out of XX, where XX are the same + var allowances = text.match(/(\d+) out of (\d+)/).slice(1,3); + expect( allowances[0] ).to.be.eq( allowances[1] ); + done(); + }) + }); + + it("Logout from user A (admin)", function(done){ + logout_user_func({ + application_host : application_host, + driver : driver, + }) + .then(function(){ done() }); + }); + + it("Login as user B", function(done){ + login_user_func({ + application_host : application_host, + user_email : email_B, + driver : driver, + }) + .then(function(){ done() }); + }); + + it("Open Book leave popup window", function(done){ + driver.findElement(By.css('#book_time_off_btn')) + .then(function(el){ return el.click() }) + .then(function(el){ + // This is very important line when working with Bootstrap modals! + return driver.sleep(1000); + }) + .then(function(){ done() }); + }); + + it("Submit leave request for the same date as the first", function(done){ + submit_form_func({ + driver : driver, + form_params : [{ + selector : 'input#from', + value : some_weekday_date, + },{ + selector : 'input#to', + value : some_weekday_date, + }], + message : /New leave request was added/, + }) + .then(function(){done()}); + }); + + it("Open requests page", function( done ){ + open_page_func({ + url : application_host + 'requests/', + driver : driver, + }) + .then(function(){ done() }); + }); + + it('Ensure that new request is in Pending status', function(done){ + driver + .findElement(By.css( 'tr.leave-request-row .leave-request-row-status' )) + .then(function(element){ + return element.getText(); + }) + .then(function(status){ + expect( status ).to.be.eq('Pending'); + done(); + }); + }); + + after(function(done){ + driver.quit().then(function(){ done(); }); + }); +}); diff --git a/views/audit/emails.hbs b/views/audit/emails.hbs index 42456b2e0..c2b53f427 100644 --- a/views/audit/emails.hbs +++ b/views/audit/emails.hbs @@ -65,7 +65,7 @@ {{# each audit_emails }} - + {{# with this.user }}{{this.full_name}}{{/with}} diff --git a/views/partials/user_requests.hbs b/views/partials/user_requests.hbs index b88f15277..7aeea035b 100644 --- a/views/partials/user_requests.hbs +++ b/views/partials/user_requests.hbs @@ -30,7 +30,7 @@ {{# each leaves }} - + {{ this.leave_type.name }}{{#if this.is_pended_revoke_leave}}
(pended revoke){{/if}} {{ this.get_deducted_days_number }} From {{#with this.get_start_leave_day}}{{as_date this.date}}{{/with}} to {{#with this.get_end_leave_day}}{{as_date this.date}}{{/with}} @@ -46,11 +46,11 @@ {{else}}
- +
{{/if}} - {{#if this.is_new_leave }}Pending{{else}}{{#if this.is_approved_leave}}Approved{{else}}Rejected{{/if}}{{/if}} + {{#if this.is_new_leave }}Pending{{else}}{{#if this.is_approved_leave}}Approved{{else}}Rejected{{/if}}{{/if}} {{/ each }} From 48a9535db10e76b43b6f6ea8755e6ad654f479a3 Mon Sep 17 00:00:00 2001 From: Pavlo Vodopyan Date: Thu, 18 May 2017 19:50:11 +0100 Subject: [PATCH 4/5] Show cancel button only for request made by currently loggedin user --- t/integration/leave_request/cancel_basic.js | 156 ++++++++++++++++++++ views/partials/user_requests.hbs | 12 +- 2 files changed, 163 insertions(+), 5 deletions(-) diff --git a/t/integration/leave_request/cancel_basic.js b/t/integration/leave_request/cancel_basic.js index 2665c0aac..8ed5435ea 100644 --- a/t/integration/leave_request/cancel_basic.js +++ b/t/integration/leave_request/cancel_basic.js @@ -337,3 +337,159 @@ describe('Leave request cancelation', function(){ driver.quit().then(function(){ done(); }); }); }); + +/* + * Scenario: + * * Create a company with admin user A and regular employee B + * * Login as employee B and submit leave request + * * Ensure that Cancel button is visible for user B + * * Login as admin user A + * * Go to user B details, ensure new reuest is there but no Cancel button + * */ +describe('Check only requestor can see the Cancel button', function(){ + + this.timeout( config.get_execution_timeout() ); + + var driver, email_A, email_B, user_id_A, user_id_B; + + it("Register new company", function(done){ + register_new_user_func({ + application_host : application_host, + }) + .then(function(data){ + driver = data.driver; + email_A = data.email; + done(); + }); + }); + + it("Create second user B", function(done){ + add_new_user_func({ + application_host : application_host, + driver : driver, + }) + .then(function(data){ + email_B = data.new_user_email; + done(); + }); + }); + + it("Obtain information about admin user A", function(done){ + user_info_func({ + driver : driver, + email : email_A, + }) + .then(function(data){ + user_id_A = data.user.id; + done(); + }); + }); + + it("Obtain information about user B", function(done){ + user_info_func({ + driver : driver, + email : email_B, + }) + .then(function(data){ + user_id_B = data.user.id; + done(); + }); + }); + + it("Logout from user A (admin)", function(done){ + logout_user_func({ + application_host : application_host, + driver : driver, + }) + .then(function(){ done() }); + }); + + it("Login as user B", function(done){ + login_user_func({ + application_host : application_host, + user_email : email_B, + driver : driver, + }) + .then(function(){ done() }); + }); + + it("Open Book leave popup window", function(done){ + driver.findElement(By.css('#book_time_off_btn')) + .then(function(el){ return el.click() }) + .then(function(el){ + // This is very important line when working with Bootstrap modals! + return driver.sleep(1000); + }) + .then(function(){ done() }); + }); + + it("Submit new leave requesti from user B for one weekday", function(done){ + submit_form_func({ + driver : driver, + form_params : [{ + selector : 'input#from', + value : some_weekday_date, + },{ + selector : 'input#to', + value : some_weekday_date, + }], + message : /New leave request was added/, + }) + .then(function(){done()}); + }); + + it("Open requests page", function( done ){ + open_page_func({ + url : application_host + 'requests/', + driver : driver, + }) + .then(function(){ done() }); + }); + + it("Ensure Cancel button is visible for user B", function(done){ + driver + .findElement(By.css( + 'tr.leave-request-row form[action="/requests/cancel/"] button[type="submit"]' + )) + .then(function(cancel_btn){ + expect( cancel_btn ).to.be.ok; + done(); + }); + }); + + it("Logout from user A (admin)", function(done){ + logout_user_func({ + application_host : application_host, + driver : driver, + }) + .then(function(){ done() }); + }); + + it("Login as admin user A", function(done){ + login_user_func({ + application_host : application_host, + user_email : email_A, + driver : driver, + }) + .then(function(){ done() }); + }); + + it('Open user B absences section', function(done){ + open_page_func({ + url : application_host + 'users/edit/'+user_id_B+'/absences/', + driver : driver, + }) + .then(function(){ done() }); + }); + + it("Ensure new reuest is there but no Cancel button", function(done){ + driver + .findElements(By.css( + 'form[action="/requests/cancel/"]' + )) + .then(function(cancel_btns){ + expect( cancel_btns.length ).to.be.eq(0); + done(); + }); + }); +}); diff --git a/views/partials/user_requests.hbs b/views/partials/user_requests.hbs index 7aeea035b..9479b338e 100644 --- a/views/partials/user_requests.hbs +++ b/views/partials/user_requests.hbs @@ -40,14 +40,16 @@ {{# unless this.is_pended_revoke_leave}}
- +
{{/unless}} {{else}} -
- - -
+ {{#if_equal this.userId ../logged_user.id }} +
+ + +
+ {{/if_equal}} {{/if}} {{#if this.is_new_leave }}Pending{{else}}{{#if this.is_approved_leave}}Approved{{else}}Rejected{{/if}}{{/if}} From c5a4eeb58044abd7a71a781584543d0907a52521 Mon Sep 17 00:00:00 2001 From: Pavlo Vodopyan Date: Thu, 18 May 2017 20:10:53 +0100 Subject: [PATCH 5/5] Update version number. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9306503be..3678a3d95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "TimeOff.Management", - "version": "0.4.4", + "version": "0.5.0", "private": false, "description": "Simple yet powerful absence management software for small and medium size business", "dependencies": {