angular.module('appServices').factory('vacationExceptionConfigService', [ function () { var statuses = ['pending', 'started', 'processed', 'cancelled']; var cancellableStatuses = ['pending', 'started']; var searchFields = ['email_colaborador', 'user_id_colaborador']; var defaultSearchField = 'email_colaborador'; var pageSize = 10; function buildInitialForm() { return { email: '', data_inicio: '', data_fim: '', emails_notificacao: '', justificativa: '' }; } return { statuses: statuses, cancellableStatuses: cancellableStatuses, searchFields: searchFields, defaultSearchField: defaultSearchField, pageSize: pageSize, buildInitialForm: buildInitialForm }; } ]); angular.module('appServices').factory('vacationExceptionFormService', [ function () { function buildCreatePayload(form) { return { email: form.email, data_inicio: form.data_inicio, data_fim: form.data_fim, emails_notificacao: form.emails_notificacao, justificativa: form.justificativa }; } return { buildCreatePayload: buildCreatePayload }; } ]); angular.module('appServices').factory('vacationExceptionPresenterService', [ 'i18nService', 'vacationExceptionConfigService', function (i18nService, vacationExceptionConfigService) { function buildSearchParams(locationParams) { var params = locationParams || {}; var query = { page: parseInt(params.page, 10) || 1, page_size: vacationExceptionConfigService.pageSize, status: vacationExceptionConfigService.statuses.indexOf(params.status) !== -1 ? params.status : null }; if (vacationExceptionConfigService.searchFields.indexOf(params.searchBy) !== -1 && params.searchValue) { query[params.searchBy] = params.searchValue; } return query; } function buildFilterState(locationParams) { var params = locationParams || {}; return { searchField: vacationExceptionConfigService.searchFields.indexOf(params.searchBy) !== -1 ? params.searchBy : vacationExceptionConfigService.defaultSearchField, searchQuery: params.searchValue || '' }; } function buildSearchChanges(filters) { var value = ((filters || {}).searchQuery || '').trim(); return { searchBy: value ? filters.searchField : null, searchValue: value || null }; } function buildLocationParams(currentParams, changes) { return angular.extend({}, currentParams, changes, { page: null }); } function canCancel(item) { return !!item && vacationExceptionConfigService.cancellableStatuses.indexOf(item.status) !== -1; } function statusLabel(status) { return i18nService.t('vacation_exception.status.' + status, { default: status }); } return { buildSearchParams: buildSearchParams, buildFilterState: buildFilterState, buildSearchChanges: buildSearchChanges, buildLocationParams: buildLocationParams, canCancel: canCancel, statusLabel: statusLabel }; } ]); angular.module('appServices').factory('vacationExceptionService', [ '$http', 'sessionService', 'cbtWorkflows', function ($http, sessionService, cbtWorkflows) { function create(payload) { return sessionService.getCurrentLoginSession() .then(function (connectionId) { return $http.post( cbtWorkflows.url + '/vacation_exceptions/new', { connection_id: connectionId, data: payload } ); }) .then(function (response) { return response.data; }); } function list(params) { return sessionService.getCurrentLoginSession() .then(function (connectionId) { return $http.get( cbtWorkflows.url + '/vacation_exceptions', { params: angular.extend({ connection_id: connectionId }, params) } ); }) .then(function (response) { return response.data; }); } function cancel(id) { return sessionService.getCurrentLoginSession() .then(function (connectionId) { return $http.put( cbtWorkflows.url + '/vacation_exception/' + encodeURIComponent(id) + '/cancel', { connection_id: connectionId } ); }) .then(function (response) { return response.data; }); } return { create: create, list: list, cancel: cancel }; } ]); angular.module('appServices').factory('customVacationExceptionValidationService', [ function () { var MAX_ADVANCE_DAYS = 45; var EMAIL_FORMAT = /^([a-z\d_\-.+]+)@(([a-z\d-]+\.)+[a-z]{2,})$/i; var EMAIL_DOMAIN_FORMAT = /^[A-Za-z0-9._%+-]+@(zayaflour\.com|positiveco\.com\.br|santaclara\.com\.br|3caffi\.com\.br|3coracoes\.com\.br)$/; function isBlank(value) { return value === null || value === undefined || String(value).trim() === ''; } function hasError(errors, field) { return errors.some(function (error) { return error.attribute === field; }); } function requiredValidation(field, code) { return function (form, errors) { if (hasError(errors, field)) { return; } if (!isBlank(form[field])) { return; } errors.push({ attribute: field, code: code || 'blank' }); }; } function formatValidation(field, format, code) { return function (form, errors) { if (hasError(errors, field)) { return; } var value = form[field]; if (isBlank(value)) { return; } if (format.test(String(value).trim())) { return; } errors.push({ attribute: field, code: code || 'invalid_format' }); }; } var validations = []; validations.push(requiredValidation('email', 'presence')); validations.push(requiredValidation('data_inicio', 'presence')); validations.push(requiredValidation('data_fim', 'presence')); validations.push(formatValidation('email', EMAIL_FORMAT, 'email_format')); validations.push(formatValidation('email', EMAIL_DOMAIN_FORMAT, 'email_domain_format')); validations.push(function (form, errors) { if (!form.data_inicio || !form.data_fim) { return; } var startDate = new Date(form.data_inicio); var endDate = new Date(form.data_fim); if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) { errors.push({ attribute: 'data_fim', code: 'date_invalid' }); return; } if (endDate <= startDate) { errors.push({ attribute: 'data_fim', code: 'date_range_invalid' }); } }); validations.push(function (form, errors) { if (!form.data_inicio) { return; } var startDate = new Date(form.data_inicio); if (isNaN(startDate.getTime())) { return; } var now = new Date(); now.setSeconds(0, 0); if (startDate < now) { errors.push({ attribute: 'data_inicio', code: 'start_date_in_past' }); } }); validations.push(function (form, errors) { if (!form.data_inicio) { return; } var startDate = new Date(form.data_inicio); if (isNaN(startDate.getTime())) { return; } var now = new Date(); now.setSeconds(0, 0); var limit = now.getTime() + MAX_ADVANCE_DAYS * 24 * 60 * 60 * 1000; if (startDate.getTime() > limit) { errors.push({ attribute: 'data_inicio', code: 'start_date_too_far' }); } }); function validate(form) { var errors = []; validations.forEach(function (validation) { validation(form, errors); }); return errors; } return { validations: validations, validate: validate }; } ]); angular.module('appControllers').controller('VacationExceptionController', ['$scope', '$location', 'appConfig', 'user', 'alertService', 'i18nService', 'errorService', 'vacationExceptionConfigService', 'vacationExceptionFormService', 'vacationExceptionService', 'customVacationExceptionValidationService', function ($scope, $location, appConfig, user, alertService, i18n, errorService, vacationExceptionConfigService, vacationExceptionFormService, vacationExceptionService, customVacationExceptionValidationService) { function onInit() { $scope.form = vacationExceptionConfigService.buildInitialForm(); $scope.user = user; $scope.alerts = alertService.get(); $scope.appConfig = appConfig; } $scope.createVacationException = function () { var errors; var payload; alertService.clear(); errors = customVacationExceptionValidationService.validate($scope.form); if (errors.length > 0) { errorService.handle({ responseJSON: { errors: errors } }, 'vacation_exception'); return; } payload = vacationExceptionFormService.buildCreatePayload($scope.form); vacationExceptionService.create(payload) .then(function () { alertService.add(i18n.t('vacation_exception.created_successfully')); $location.path('/vacation_exceptions'); }) .catch(function (response) { var data = response && response.data; if (data && Array.isArray(data.errors)) { errorService.handle({ responseJSON: data }, 'vacation_exception'); return; } errorService.handle(data ? i18n.t(data) : response, 'vacation_exception'); }); }; onInit(); } ]); angular.module('appControllers').controller('VacationExceptionsController', ['$scope', '$location', '$window', 'user', 'alertService', 'i18nService', 'errorService', 'paginationService', 'vacationExceptionService', 'vacationExceptionPresenterService', function ($scope, $location, $window, user, alertService, i18n, errorService, paginationService, vacationExceptionService, vacationExceptionPresenterService) { function onInit() { $scope.user = user; $scope.alerts = alertService.get(); $scope.canCancel = vacationExceptionPresenterService.canCancel; $scope.statusLabel = vacationExceptionPresenterService.statusLabel; $scope.searchVacationExceptions(); } $scope.$on('$locationChangeSuccess', function () { if ($location.path() !== '/vacation_exceptions') { return; } $scope.searchVacationExceptions(); }); function handleError(response) { errorService.handle(response && response.data ? i18n.t(response.data) : response, 'vacation_exception'); } $scope.searchVacationExceptions = function () { var query = vacationExceptionPresenterService.buildSearchParams($location.search()); $scope.vacation_exceptions_search = null; vacationExceptionService.list(query) .then(function (data) { $scope.vacation_exceptions_search = data; $scope.pagination = paginationService.build(data, query); }) .catch(function (response) { $scope.vacation_exceptions_search = { count: 0, results: [] }; handleError(response); }); }; $scope.cancel = function (item) { if (!vacationExceptionPresenterService.canCancel(item)) { return; } if (!$window.confirm(i18n.t('vacation_exception.list.cancel_confirm'))) { return; } alertService.clear(); vacationExceptionService.cancel(item._id.$oid) .then(function () { alertService.add(i18n.t('vacation_exception.cancelled_successfully')); $scope.searchVacationExceptions(); }) .catch(handleError); }; onInit(); } ]); // ===== Routes ===== var vacationExceptionAccessGuard = function (resource, action) { return function ($q, $location, configService) { return configService.get().then(function (config) { if (config.permissions?.[resource]?.[action]) { return true; } $location.path('/profile'); return $q.reject('not_authorized'); }); }; }; vacationExceptionAccessGuard.$inject = ['$q', '$location', 'employeeService']; vacationExceptionCustomPortalRoutes = [ { path: '/vacation_exceptions', templateUrl: 'vacation_exceptions.html', controller: 'VacationExceptionsController', resolve: { user: 'loggedInUser', permission: vacationExceptionAccessGuard('vacation_exception', 'read') } }, { path: '/vacation_exceptions/new', templateUrl: 'vacation_exception.html', controller: 'VacationExceptionController', resolve: { user: 'loggedInUser', permission: vacationExceptionAccessGuard('vacation_exception', 'create') } } ]; customPortalRoutes.push(...vacationExceptionCustomPortalRoutes) angular.module('appDirectives').directive('vacationExceptionsSearch', function () { return { restrict: 'E', templateUrl: 'templates/vacation_exceptions_search.html', scope: true, link: function (scope, element, attrs) { scope.includeFilters = attrs.includeFilters == 'true'; } }; } ); angular.module('appDirectives').directive('vacationExceptionsSearchFilters', ['$location', 'alertService', 'vacationExceptionConfigService', 'vacationExceptionPresenterService', function ($location, alertService, vacationExceptionConfigService, vacationExceptionPresenterService) { return { restrict: 'E', templateUrl: 'templates/vacation_exceptions_search_filters.html', scope: true, link: function (scope) { scope.statuses = vacationExceptionConfigService.statuses; scope.filters = vacationExceptionPresenterService.buildFilterState($location.search()); scope.currentStatus = function () { return $location.search().status || null; }; function applyParams(changes) { alertService.clear(); $location.search(vacationExceptionPresenterService.buildLocationParams($location.search(), changes)); } scope.search = function () { applyParams(vacationExceptionPresenterService.buildSearchChanges(scope.filters)); }; scope.toggleStatus = function (status) { applyParams({ status: status }); }; } }; } ]); angular.module('appDirectives').directive('vacationExceptionsResultTable', function () { return { restrict: 'E', templateUrl: 'templates/vacation_exceptions_result_table.html', scope: true }; } );