app.controller('QuotationFinalizationCtrl', function($scope, $http, $window, $routeParams, $location, $filter) { $scope.isLoadingQuotation = true; $scope.isLoadingPayment = false; $scope.paymentMethods = {0: 'Ideal', 1: 'Bank transfer'}; $scope.btwCheck = true; $scope.hotelRoomString = ''; //define components $scope.hasCamp = false; $scope.hasHotel = false; $scope.hasFlight = false; $scope.quotationNumber = ""; //show option to go incognito or switch to customer account $scope.blnLoginToggle = false; function generateHotelRoomString(field) { let rooms = {}; if (field['value'] !== undefined && Array.isArray(field['value']) && field['value'].length) { field['value'].forEach((room) => { if (room['name'] !== undefined && room['name'] && room['amount'] !== undefined && room['amount']) { rooms[room['name']] = room['amount']; } }); let orderedRooms = {}; Object.keys(rooms).sort().forEach((key) => { $scope.hotelRoomString = $scope.hotelRoomString + rooms[key] + 'x ' + key + "\n\r"; }); } } // Go to the next page $scope.nextPage = function() { if ($scope.currentPage < 7) { // Check the current page data if ($scope.checkPageData()) { // Check OK? Load the new page $scope.setPageData($scope.currentPage + 1); } } } $scope.resetSignature = function() { delete $scope.rawQuotation.signature; } // Go to the previous page $scope.previousPage = function() { if ($scope.currentPage > 1 && $scope.currentPage !== 4) { // Load the new page $scope.setPageData($scope.currentPage - 1); } } $scope.goToPage = function(page) { if (page < $scope.currentPage) { // Load the new page $scope.setPageData(page); } } // Toggle: view the general conditions $scope.toggleConditions = function() { $scope.showConditions ^= 1; } $scope.addDays = function(date, addition) { date = new Date(date); return date.setDate(date.getDate() + addition); } // Accept the quotation $scope.accept = function() { //set loading and to page 4 $scope.isLoadingPayment = true; $scope.currentPage = 4; var req = { method: 'POST', url: '/quotation/accept/' + $routeParams.hash, data: { fields: $scope.rawQuotation.fields, signature: $scope.rawQuotation.signature, conditionsOK: $scope.rawQuotation.conditionsOK, publicationOK: $scope.rawQuotation.publicationOK, newsLetterOk: $scope.rawQuotation.newsLetterOk, }, } $http(req).then(function(response) { // If status true send to the payment page if (response.status && response.data.status && response.data.data.link) { $scope.isLoadingPayment = false; $scope.paymentSuccess = true; setTimeout(function(){ window.location.replace(response.data.data.link) }, 5000); } else if (response.status && response.data.status) { $scope.isLoadingPayment = false; $scope.paymentSuccess = false; } else { // swal to customer swal({ title: 'Error', text: response.data.message, icon: 'warning', }); // back to previous screen $scope.isLoadingPayment = false; $scope.currentPage = 3; } }); } // The quotation is declined $scope.declineOkFunction = function() { $scope.rawQuotation.header.status = 'Geweigerd'; } // Set the missing field options $scope.setMissingFieldOptions = function() { angular.forEach($scope.rawQuotation.fields, function(field, key) { if (field.ask_validation == true && field.subtype != 'vatcode') { // If this is a select box, get the options if ((field.type == 'select') && field.controller) { $scope.getOptions(field); $scope.rawQuotation.fields[key] = field; } } }); } // Get the options for the field $scope.getOptions = function(field) { if (field.function && field.function.length) { get_function = field.function; } else { get_function = 'get'; } // Get the fields var req = { method: 'GET', url: '/' + field.controller + '/' + get_function, } $http(req).then(function(response) { // Success? Set the options if (response.status && response.data.status) { // For the client, add the option 'New client' if (field.name == 'Klant') { field.options = [ {name: 'Nieuwe klant'} ]; response.data.data.forEach(function(option) { field.options.push(option); }); } else { field.options = response.data.data; } $scope.onChange(field); } else { // Error swal({ title: 'Error', text: response.data.message, icon: 'warning', }); } }); } // Check the current page data $scope.checkPageData = function() { switch ($scope.currentPage) { case 1: // Check the open questions break; case 2: // Check the open questions break; case 3: // Check the quotation is accepted $scope.accept(); return false; break; /* case *: // Check the number of participants $scope.getNumOfParticipants(); return false; break; case *: // Check the rooming list $scope.$broadcast('getAvailableAttendees'); return false; break; */ } return true; } $scope.getNumOfParticipants = function() { $scope.$broadcast('getNumOfParticipants') } $scope.$on('returnNumOfParticipants', function(e, data) { if (data >= $scope.pax) { $scope.setPageData($scope.currentPage + 1); } else { swal("Let op!", "U heeft nog " + ($scope.pax - data) + " deelnemer(s) toe te voegen.", "warning") } }) $scope.$on('pingBack', function(e,data) { $scope.availableAttendees = data; // If >= 1 attendee is not assigned to a room if ($scope.availableAttendees.length) { $scope.pageMsg = 'Deel iedere deelnemer in een kamer in en klik op \'Oplaan\'.'; } else { // Go to the next page $scope.setPageData($scope.currentPage + 1); } }) $scope.setPeriod = function(from, till) { fromDate = $scope.convertDateObjToJS(from, false, 'date'); if (fromDate) { tillDate = $scope.convertDateObjToJS(till, false, 'date'); if (tillDate) { if (typeof fromDate == 'object') { $scope.period = $filter('date')($scope.convertDate(fromDate)) + ' t/m ' + $filter('date')($scope.convertDate(tillDate)); } else { $scope.period = fromDate + ' t/m ' + tillDate; } } } } $scope.getNumberOfNights = function(from, till) { from = from.split("-"); from = from[0] + '/' + from[1].padStart(2, '0') + '/' + from[2].padStart(2, '0'); till = till.split("-"); till = till[0] + '/' + till[1].padStart(2, '0') + '/' + till[2].padStart(2, '0'); var date1 = new Date(from); var date2 = new Date(till); var timeDiff = Math.abs(date2.getTime() - date1.getTime()); var numberOfNights = Math.ceil(timeDiff / (1000 * 3600 * 24)); return numberOfNights; } $scope.setPlainData = function() { $scope['quotationData'] = {}; angular.forEach($scope.rawQuotation.fields, function(field, key) { $scope[field.subtype] = field.value; if (field.subtype == 'flights' && typeof $scope[field.subtype] == 'string'){ try{ $scope['quotationData'][field.subtype] = JSON.parse(field.value); } catch (e) { $scope['quotationData'][field.subtype] = field.value; } } else { $scope['quotationData'][field.subtype] = field.value; } }, $scope); // Format the rooms/room types for the contract page // Count the number of x-person rooms $scope.roomTypes = {}; angular.forEach($scope.rooms, function(room) { numOfBeds = 0; if (room.singles) { numOfBeds = room.singles; } if (room.doubles) { numOfBeds += 2*room.doubles; } if (typeof $scope.roomTypes[numOfBeds] === 'undefined') { $scope.roomTypes[numOfBeds] = 1; } else { $scope.roomTypes[numOfBeds]++; } }); // Format the dates if ($scope.canceldate) { canceldate = $scope.convertDateObjToJS($scope.canceldate, false, 'date'); $scope.canceldate = canceldate.toLocaleDateString() } } // Process/format the quotation data $scope.formatData = function() { if ($scope.rawQuotation && $scope.rawQuotation.fields) { // Format the raw data // Get relevant data $scope.setPlainData(); $scope.setPeriod($scope.from, $scope.till); $scope.numOfMatches = 0; angular.forEach($scope.activities, function(activity) { // Calculate the number of minutes per training durationDate = $scope.convertDateObjToJS(activity.duration, false, 'time'); // Round by 5 minutes if(durationDate != undefined){ activity.minutes = 60*durationDate.getHours() + 5*Math.round(durationDate.getMinutes()/5); } // Count the number of football matches if (activity.football_match && activity.football_match.id) { $scope.numOfMatches++; } }) // Calculate the total price totalPrice = $scope.pax * $scope.pricepp; // initiate deposit amount let depositAmount = null; if ($scope.rawQuotation.header !== undefined && typeof $scope.rawQuotation.header == 'object' && $scope.rawQuotation.header.deposit_amount !== undefined && $scope.rawQuotation.header.deposit_amount) { // set given deposit amount depositAmount = $scope.rawQuotation.header.deposit_amount; } else { // fallback to default calculation depositAmount = Math.ceil(0.3 * totalPrice); } // Set the pre-payment price $scope.prePaymentAmount = depositAmount; // Set the rest payment amount: 70% fromDate = $scope.convertDateObjToJS($scope.from, false, 'date'); fromDate.setDate(fromDate.getDate() - 30); // 30 days before departure $scope.restPaymentDate = fromDate; } } // Count #missing fields $scope.countMissingFields = function () { $scope.numOfMissingFields = 0 angular.forEach($scope.rawQuotation.fields, function(field) { if (field.ask_validation && field.subtype != 'vatcode') { $scope.numOfMissingFields++ } }) } // Set the page data $scope.setPageData = function(pageNum) { $scope.currentPage = pageNum; $scope.pageMsg = null; // Load the data if these are not loaded before if ($scope.rawQuotation == undefined) { $scope.rawQuotation = {}; var req = { method: 'GET', url: '/quotation/getForCustomerOverview/' + $routeParams.hash, } $http(req).then(function(response) { delete $scope.isLoadingQuotation; // If status true send to the dashboard page if (response.data.status) { //set data let data = {}; if (response.data.data && response.data.data.data) { data = response.data.data.data; } // Set the quotation data $scope.rawQuotation.fields = (data.fields ? Object.values(data.fields) : []); $scope.rawQuotation.header = response.data.data.header; //check if quotation has validation fields function checkAskValidation(data) { const fields = data; for (const fieldId in fields) { if (fields[fieldId].ask_validation === true) { return true; } } return false; } $scope.hasValidationFields = checkAskValidation($scope.rawQuotation.fields); // Helper functions to get the page number and array of pages $scope.getPageArray = function() { return $scope.hasValidationFields ? [1, 2, 3, 4] : [1, 3, 4]; }; $scope.getPageNumber = function(index) { return $scope.hasValidationFields ? index + 1 : (index >= 1 ? index + 2 : index + 1); }; //set components $scope.hasCamp = (data.hasCamp ? data.hasCamp : false); $scope.hasHotel = (data.hasHotel ? data.hasHotel : false); $scope.hasFlight = (data.hasHotel ? data.hasHotel : false); $scope.quotationNumber = (data.quotation_number ? data.quotation_number : false); //check if quotation has been accepted if ($scope.rawQuotation.header && $scope.rawQuotation.header.status && $scope.rawQuotation.header.status == 'Geaccepteerd' && $scope.rawQuotation.header.payment_id){ $scope.currentPage = 4; $scope.payment_id = $scope.rawQuotation.header.payment_id; getPaymentData(); getPaymentMethodDetails(); } $scope.customerData = response.data.data.customer; if ($scope.customerData['images'] !== undefined) { $scope.customerData.images = JSON.parse($scope.customerData.images); } angular.forEach($scope.rawQuotation.fields, function (field, key) { switch (field.type) { case 'flights': $scope.baggage = false; $scope.handBaggage = false; angular.forEach(field.value, function (flight, key) { //hand baggage if(flight.handBaggageKG != undefined && ($scope.handBaggage == false)){ $scope.handBaggage = parseInt(flight.handBaggageKG) }else if(flight.handBaggageKG != undefined && (parseInt(flight.handBaggageKG) < $scope.handBaggage)){ $scope.handBaggage = parseInt(flight.handBaggageKG) } // baggage if(flight.baggageKG != undefined && ($scope.baggage == false)){ $scope.baggage = parseInt(flight.baggageKG) }else if(flight.baggageKG != undefined && (parseInt(flight.baggageKG) < $scope.baggage)){ $scope.baggage = parseInt(flight.baggageKG) } }) $scope.flights = field.value; break; case 'hotel': $scope.hotels = field.value; break; case 'chambers': generateHotelRoomString(field); break; } if(field.subtype == 'club'){ $scope.club = field.value; } if(field.subtype == 'activities'){ angular.forEach(field.value, function (activity, key) { if(activity.activity_type != undefined){ activity.activity_type = JSON.parse(activity.activity_type); } }) } }); // Process/format the retrieved data $scope.setMissingFieldOptions(); $scope.formatData(); $scope.countMissingFields() $scope.createScenario(); } // If status false give error message else { if (response.data.data && response.data.data.header && response.data.data.header.status == 'expired'){ $scope.rawQuotation.header = response.data.data.header; } else { // Error swal("Foutmelding", "De offertegegevens konden niet opgehaald worden.", "error"); } } }, function(error) { delete $scope.isLoadingQuotation; }); } switch (pageNum) { case 2: // If there are no open questions if ($scope.numOfMissingFields == 0) { $scope.currentPage++ } break; case 3: // Set the data for the contract page by subtype $scope.setPlainData(); break; } } // Load the page $scope.createScenario = function() { if ((typeof $scope.scenarioId == 'undefined') || ($scope.scenarioId == 0) || (!(parseInt($scope.scenarioId) > 0))) { $scope.scenarioId = 0; // Create a new scenario var req = { method: 'GET', url: '/scenario/createFromQuotation/' + $routeParams.hash, } $http(req).then(function(response) { // If status true send to the dashboard page if (response.data.status) { $scope.scenarioId = response.data.data.id; if (!(parseInt($scope.scenarioId) > 0)) { swal("Foutmelding", "Het draaiboek kon niet aangemaakt worden.", "error"); return; } } // If status false give error message else { // Wrong data swal("Foutmelding", "Het draaiboek kon niet aangemaakt worden.", "error"); } }); } } // Get the date month name $scope.monthName = function(dt){ mlist = ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"]; return mlist[dt.getMonth()]; }; // Get the date month name $scope.monthNameByNumber = function(dt){ mlist = ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"]; return mlist[dt]; }; // Load the page $scope.loadPage = function() { // fetch countries $scope.getCountries(); // fetch payment details getPaymentData(); getPaymentMethodDetails(); // Set the page titles $scope.titles = [ 'Offerte', 'Openstaande vragen', // 'Deelnemers', // 'Kamerlijsten', 'Overeenkomst', '', 'Betaling', ]; // Show the general conditions by default $scope.showConditions = false; // Set the current date $scope.today = new Date(); // Load the first page $scope.setPageData(1); } $scope.convertHour = function(dateString) { let date = {}; if (typeof dateString === 'string'){ date = new Date(dateString); } else { date = dateString; } let hours = date.getHours(); let minutes = date.getMinutes(); if (hours < 10) { hours = '0' + hours; } if (minutes < 10) { minutes = '0' + minutes; } return hours + ':' + minutes; } $scope.convertTime = function(dateString) { return (dateString.substr(11,5)); } $scope.convertDate = function(dateString) { //check format let regex = new RegExp('[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}T[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}.[0-9]+[Z]?'); let regexDate = new RegExp('[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}'); let dutchDate = ""; if (regexDate.test(String(dateString))) { resDate = String(dateString).split("T"); if (resDate[0] !== undefined) { resDate = resDate[0].split("-"); if (resDate[0] !== undefined && resDate[1] !== undefined && resDate[2] !== undefined) { strYear = resDate[0]; strMonth = resDate[1].padStart(2, '0'); strDay = resDate[2].substring(0, 2).padStart(2, '0'); } } dutchDate = strDay + ' ' + $scope.monthNameByNumber(parseInt(strMonth) - 1) + ' ' + strYear; } else { let date = {}; if (typeof dateString !== 'object'){ date = new Date(dateString); } else { date = dateString; } let day = date.getDate(); if (day < 10) { day = '0' + day; } dutchDate = day + ' ' + $scope.monthName(date) + ' ' + date.getFullYear(); } return dutchDate; } $scope.convertDateObjToJS = function(objDate, reverse, type) { if (!objDate) { return objDate; } if(!reverse){ if (typeof objDate == 'object') { return objDate; } tempTime = objDate.split(/[- :]/); switch(type){ case 'date': tempNewTime = new Date(tempTime[0], tempTime[1]-1, tempTime[2], 0, 0, 0); break; case 'time': if(!tempTime[2]){ tempTime[2] = 0; } tempNewTime = new Date(0 ,0, 0, tempTime[0], tempTime[1], 0); break; case 'datetime': tempNewTime = new Date(tempTime[0], tempTime[1]-1, tempTime[2], tempTime[3], tempTime[4], tempTime[5]); break; } return tempNewTime; }else{ if (typeof objDate == 'string') { return objDate; } switch(type){ case 'date': if(typeof objDate.getFullYear !== 'function'){ return null; } return ([objDate.getFullYear(), objDate.getMonth()+1, objDate.getDate()].join('-')); break; case 'time': if(typeof objDate.getHours !== 'function'){ return null; } return ([('00' + objDate.getHours()).slice(-2), ('00' + objDate.getMinutes()).slice(-2)].join(':')); break; case 'datetime': if(typeof objDate.getFullYear !== 'function'){ return null; } return ([objDate.getFullYear(), objDate.getMonth()+1, objDate.getDate()].join('-')+' '+[('00' + objDate.getHours()).slice(-2), ('00' + objDate.getMinutes()).slice(-2)].join(':')); break; default: return objDate; break; } } } $scope.getSelectOptions = function(field){ if(field.name == "Land"){ field.options = $scope.countries; } return []; } $scope.getCountries = function(){ // get countries var req = { method: 'GET', url: '/country/getNames', } $http(req).then(function(response) { // Success? if (response.status && response.data.status) { $scope.countries = response.data.data; } }); } //after change $scope.onChange = function(field){ } /* PAYMENT FUNCTIONS */ $scope.payMethods = []; $scope.payment = { id: $routeParams.id, amount: null, description: '', method: '', }; function getPaymentMethodDetails() { var req = { method: 'GET', url: '/payment/getPaymentMethodDetails', } $http(req).then(function(response) { if (response.status && response.data.status) { $scope.payMethods = response.data.data; } }); } function getPaymentData() { if($scope.payment_id != undefined){ var req = { method: 'GET', url: '/payment/get/' + $scope.payment_id, } $http(req).then(function(response) { if (response.status && response.data.status) { $scope.payment = response.data.data; if ($scope.paymentData === undefined){ $scope.paymentData = response.data.data; } } }); } } $scope.do = function(paymentData) { $scope.paymentLoading = true // Set the payment method if method is chosen if (paymentData.paymentMethod && paymentData.paymentMethod.id) { $scope.payment.method = paymentData.paymentMethod.id; $scope.payment.scenario_id = ($scope.scenarioId != undefined ? $scope.scenarioId : null); $scope.payment.customer_id = ($scope.rawQuotation.header.customer_id != undefined ? $scope.rawQuotation.header.customer_id : null); $scope.payment.method = paymentData.paymentMethod.id; if($scope.payment_id != undefined){ // Post the payment var req = { method: 'POST', url: '/payment/do/' + $scope.payment_id, data: $scope.payment, } $http(req).then(function(response) { if (response.status && response.data.status && response.data.data.link) { // Follow the link window.location.replace(response.data.data.link); } else { // Error swal({ title: 'Foutmelding', text: response.data.message, icon: 'warning', }); } }); } } else { swal({ title: 'Foutmelding', text: 'Kies een betaalmethode', icon: 'warning', }); } } function init() { // If a token is set, login if (($routeParams['token'] != undefined) && ($scope.user == undefined)) { //check if there is a session already var req = { method: 'GET', url: '/user/check', } $http(req).then(function(response) { // check the status of the response if (response.data.status) { // User is already logged in, show popup with actions $scope.currentUserName = response.data.data.name; $scope.currentURL = window.location.href; $scope.blnLoginToggle = true; } else { $scope.login(); } }); } else { // load page // fetch countries $scope.getCountries(); // Set the page titles $scope.titles = [ 'Offerte', ]; // Set the current date $scope.today = new Date(); // Load the first page $scope.currentPage = 1; $scope.pageMsg = null; // Load the data if these are not loaded before if ($scope.rawQuotation == undefined) { $scope.rawQuotation = {}; var req = { method: 'GET', url: '/quotation/getForCustomerOverview/' + $routeParams.hash, } $http(req).then(function(response) { delete $scope.isLoadingQuotation; // If status true send to the dashboard page if (response.data.status) { //set data let data = {}; if (response.data.data && response.data.data.data) { data = response.data.data.data; } // Set the quotation data $scope.rawQuotation.fields = (data.fields ? Object.values(data.fields) : []); $scope.rawQuotation.header = response.data.data.header; //set components $scope.hasCamp = (data.hasCamp ? data.hasCamp : false); $scope.hasHotel = (data.hasHotel ? data.hasHotel : false); $scope.hasFlight = (data.hasHotel ? data.hasHotel : false); $scope.customerData = response.data.data.customer; if ($scope.customerData['images'] !== undefined) { $scope.customerData.images = JSON.parse($scope.customerData.images); } angular.forEach($scope.rawQuotation.fields, function (field, key) { switch (field.type) { case 'flights': $scope.baggage = false; $scope.handBaggage = false; angular.forEach(field.value, function (flight, key) { //hand baggage if(flight.handBaggageKG != undefined && ($scope.handBaggage == false)){ $scope.handBaggage = parseInt(flight.handBaggageKG) }else if(flight.handBaggageKG != undefined && (parseInt(flight.handBaggageKG) < $scope.handBaggage)){ $scope.handBaggage = parseInt(flight.handBaggageKG) } // baggage if(flight.baggageKG != undefined && ($scope.baggage == false)){ $scope.baggage = parseInt(flight.baggageKG) }else if(flight.baggageKG != undefined && (parseInt(flight.baggageKG) < $scope.baggage)){ $scope.baggage = parseInt(flight.baggageKG) } }) $scope.flights = field.value; break; case 'hotel': $scope.hotels = field.value; break; case 'chambers': generateHotelRoomString(field); break; } if(field.subtype == 'club'){ $scope.club = field.value; } if(field.subtype == 'activities'){ angular.forEach(field.value, function (activity, key) { if(activity.activity_type != undefined){ activity.activity_type = JSON.parse(activity.activity_type); } }) } }); // Process/format the retrieved data $scope.setMissingFieldOptions(); $scope.formatData(); } // If status false give error message else { if (response.data.data && response.data.data.header && response.data.data.header.status == 'expired'){ $scope.rawQuotation.header = response.data.data.header; } else { // Error swal("Foutmelding", "De offertegegevens konden niet opgehaald worden.", "error"); } } }, function(error) { delete $scope.isLoadingQuotation; }); } } } $scope.login = function() { // Login $scope.blnLoginToggle = false; var req = { method: 'POST', url: '/user_login/tokenlogin/' + $routeParams['token'], } $http(req).then(function(response) { // If status true send to the dashboard page if (response.data.status) { $scope.user = response.data.data; // load page $scope.loadPage(); } // If status false give error message else { // Wrong data $scope.isLoadingQuotation = false; swal("Ongeldige offerte", "De offerte is niet meer geldig, neem even contact met ons op!", "error"); } }); } init(); });