cobuild-angular-stack
Version:
Base stack angular sass jade gulp
815 lines (739 loc) • 34 kB
JavaScript
(function (module) {
'use strict';
module.controller('MainCheckoutController', MainCheckoutController);
module.controller('SuccessOrderController', SuccessOrderController);
MainCheckoutController.$inject = [
'$scope', '$rootScope', '$state', '$stateParams', 'CoupleAccount', 'Guest', 'toastr', '$localStorage',
'countries', '$timeout', 'currencies', 'currencyConversionPromiseFilter', 'currencyFilter', '$analytics',
'$translate', 'Order', 'Card', 'account', 'lodash', '$interval'
];
function MainCheckoutController($scope, $rootScope, $state, $stateParams, CoupleAccount, Guest, toastr, $localStorage,
countries, $timeout, currencies, currencyConversion, currency, $analytics, $translate, Order,
Card, account, lodash, $interval) {
var steps = ['guest.checkout.cart', 'guest.checkout.message', 'guest.checkout.pay', 'guest.checkout.receipt'];
$scope.validPhone = /^\d{7,12}$/;
$scope.validateForm = {};
$scope.goStep = function (step) {
var currentStep = steps.indexOf($state.$current.name);
if (currentStep < 0 || step > currentStep) {
$translate('error-steps').then(function (translation) {
return toastr.error(translation);
});
}
$state.go(steps[step]);
};
// $state.go('guest.checkout.receipt')
$scope.print = function (order, coupleAccount) {
var buttonPrintData = {
order: order.fakeid,
couple: (coupleAccount.weddingData.nameP1 || '') + ' & ' + (coupleAccount.weddingData.nameP2 || ''),
amount: 'MX$ ' + order.paymentData.amount.formatMoney(2),
comission: 'MX$ ' + (order.comission || 0).formatMoney(2),
total: 'MX$ ' + (order.paymentData.amount + order.comission).formatMoney(2),
barcode_url: order.transactionData.payment_method.barcode_url,
barcode: order.transactionData.payment_method.barcode
};
var serialize = function(obj) {
var str = [];
for(var p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
};
window.open('http://front.uniko.co/partials/print.html?' + serialize(buttonPrintData), '', 'width=700,height=700');
};
$scope.$state = $state;
$scope.account = null;
$scope.products = [];
$scope.url = $stateParams.url;
$scope.birthdate = {};
$scope.address = {};
var currentYear = new Date().getFullYear();
$scope.months = lodash.range(1, 13);
$scope.years = lodash.range(currentYear, currentYear + 11);
$scope.birthyears = lodash.reverse(lodash.range(currentYear - 90, currentYear - 17));
$scope.countries = countries;
$scope.mercadoMedios = {};
$scope.getDaysArray = function (year, month) {
var date = new Date(year, month - 1, 1);
var result = [];
while (date.getMonth() == month - 1) {
result.push(date.getDate());
date.setDate(date.getDate() + 1);
}
return result;
};
$scope.currencies = currencies;
$scope.currency = lodash.find(currencies, {code: 'MXN'});
$scope.selectCurrency = function (currency) {
$scope.currency = currency;
};
$scope.pay = {
month: null,
year: null
};
$scope.payer = {};
$scope.paymentInfo = {};
$scope.disabled = false;
$scope.order = null;
$scope.removeItem = function (index) {
$scope.products.splice(index, 1);
};
var findMercadoMedios = function(){
console.log('findMercadoMedios');
Guest.getMercadoPayments(function (medios) {
console.log('Medios = ', medios);
$scope.mercadoMedios = medios;
console.log('Medios 2 = ', $scope.mercadoMedios);
});
};
findMercadoMedios();
var $w = function (newVal) {
if (!$scope.products) {
return;
}
var total = 0;
lodash.forEach($scope.products, function (product) {
var price = Math.$round(product.price, 2);
total += price * product.bought;
currencyConversion(price * product.bought, 'MXN', $scope.currency.code).then(function (price) {
product.convertedPrice = currency(price, $scope.currency.symbol + ' ', 2);
});
});
currencyConversion(total, 'MXN', $scope.currency.code).then(function (price) {
$scope.total = currency(price, $scope.currency.symbol + ' ', 2);
var paymentInfo = $scope.paymentInfo;
var number = 'transfer';
if (paymentInfo.method === 'cc') {
number = paymentInfo.pay.number || '';
} else if (paymentInfo.method === 'paypal') {
number = 'paypal';
} else if (paymentInfo.method === 'ox') {
number = 'oxxo';
} else if (paymentInfo.method === 'mercado') {
number = 'mercado';
}
Card.calculateComission({
cardNumber: number,
value: total
}, function (response) {
console.log(response);
currencyConversion(response.comission, 'MXN', $scope.currency.code).then(function (comission) {
console.log(comission);
$scope.comission = currency(comission, $scope.currency.symbol + ' ', 2);
});
currencyConversion(Math.$round(response.comission + total, 2), 'MXN', $scope.currency.code).then(function (totalAndComission) {
$scope.totalAndComission = currency(totalAndComission, $scope.currency.symbol + ' ', 2);
});
});
});
$scope.totalMx = currency(total, 'MXN ', 2);
};
$scope.updatePrices = function (item, element) {
$w();
};
$scope.$watchGroup(['products', 'products.length', 'currency', 'paymentInfo.method', 'paymentInfo.pay.number'], $w);
this.step3 = function () {
$analytics.eventTrack('Messages', {'Messages': true});
$state.go("guest.checkout.pay", {url: $scope.url});
};
function loadPaymentInfo() {
var paymentInfo = lodash.cloneDeep($scope.paymentInfo);
paymentInfo.birthdate = $scope.birthdate;
if (paymentInfo.pay && paymentInfo.payer)
paymentInfo.pay.name = paymentInfo.payer.fullname;
paymentInfo.urlRegistry = $scope.url;
paymentInfo.address = $scope.address;
paymentInfo.products = [];
lodash.forEach($scope.products, function (product) {
for (var i = 0; i < product.bought; i++) {
paymentInfo.products.push(product.id);
}
});
return paymentInfo;
}
var ExceptionForm = function(message, element) {
this.message = message;
this.element = element;
}
var CardValidate = function(number, element) {
this.number = number;
this.element = element;
this.type_card = "";
this.is_valid_number = false;
this._typeCard = function() {
var id = String(this.number).substring(0,1)
switch(id) {
case '6':
var bin_60 = String(this.number).substring(0,4);
var bin_range_62 = String(this.number).substring(0,6);
var bin_range_64 = String(this.number).substring(0,3);
var bin_65 = String(this.number).substring(0,2);
if(bin_60 == "6011" || (bin_range_62 >= "622126" && bin_range_62 <= "622925") || (bin_range_64 >= "644" && bin_range_64 <= "649") || bin_65 == "65") {
this.type_card = "discover"
}
break;
case '3':
var bin_range = String(this.number).substring(0,2);
if(bin_range == "34" || bin_range == "37") {
this.type_card = "amex"
}
break;
case '5':
case '2':
var bin_range = String(this.number).substring(0,2);
if(bin_range >= "51" && bin_range <= "55") {
this.type_card = "mastercard";
}
break;
case '4':
this.type_card = "visa"
break;
default:
this.type_card = "visa"
//throw new ExceptionForm("No se encontro tipo de tarjeta", element);
}
$scope.paymentInfo.otro = {
pay_type: this.type_card
}
console.log("------->", $scope.paymentInfo, this.type_card);
if(this.type_card == "amex" && String(this.number).length != 15) {
throw new ExceptionForm("La tarjeta debe tener 15 dígitos", element);
} else if (this.type_card != "amex" && String(this.number).length != 16) {
throw new ExceptionForm("La tarjeta debe tener 16 dígitos", element);
}
}
this.cardValid = function() {
var type_card = this.type_card;
var operation = 0;
var cardNumber = String(this.number).split("").reverse();
this._typeCard();
var total = 0;
for(var index = 0; index < cardNumber.length; index ++) {
var positionCard = index + 1;
var number = cardNumber[index];
operation = parseInt(number);
operation = positionCard % 2 == 0 ? (operation * 2) : operation;
operation = operation > 9 ? eval(String(operation).split("").join("+")) : operation;
total = total + operation;
}
this.is_valid_number = total % 10 == 0 ? true : false;
if(!this.is_valid_number) {
throw new ExceptionForm("El número de tarjeta no es valido", element);
}
}
switch (this.number) {
case '4242424242424242':
case '4012888888881881':
case '5555555555554444':
case '5105105105105100':
case '378282246310005':
case '371449635398431':
this.is_valid_number = true;
break;
default:
this.cardValid();
}
}
var TypeData = function(type, info, element, requerid) {
this.type = type;
this.info = info;
this.element = element;
if(requerid && $.trim(this.info).length == 0) {
throw new ExceptionForm("Este campo es requerido", element);
}
switch (this.type) {
case 'integer':
if(isNaN(this.info)) {
throw new ExceptionForm("El campo debe ser numérico", element);
}
break;
case 'email':
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if(!re.test(this.info)) {
throw new ExceptionForm("El correo no es válido", element);
}
break;
case 'select':
if(!this.info) {
throw new ExceptionForm("Este campo es requerido", element);
}
break;
case 'phone':
var re = /^\(?([0-9]{3})\)?([0-9]{3})[-. ]?([0-9]{1,4})$/
if(!re.test(this.info)){
throw new ExceptionForm("No es un teléfono válido", element);
}
}
}
$scope.onValidateInput = function(element, info, compare_info, isKeyup) {
var verify = function() {
$scope.validateForm[element+"_error"] = "";
try {
switch (element) {
case 'card_number' :
var valid_type = new TypeData('integer', info, element, true);
break;
case 'year':
case 'month':
case 'day':
case 'pay_type':
case 'exp_year':
var valid_type = new TypeData('select', info, element, true);
break;
case 'cvc':
var valid_type = new TypeData('integer', info, element, true);
break;
case 'confirmEmail':
var valid_type = new TypeData('email', info, element, true);
if(info != compare_info) {
throw new ExceptionForm("El correo no coincide", element);
}
break;
case 'phone':
var valid_type = new TypeData('phone', info, element);
break;
case 'email':
var valid_type = new TypeData('email', info, element, true);
break;
default:
var valid_type = new TypeData('string', info, element, true);
}
} catch (e) {
$scope.validateForm[e.element+"_error"] = e.message;
}
}
if(isKeyup && $scope.validateForm[element+"_error"] && $scope.validateForm[element+"_error"].length >0) {
verify();
} else if(!isKeyup) {
verify();
} else {
if(element == "card_number") var card =new CardValidate(info, element);
}
}
$scope.validateDataPayment = function() {
var paymentInfo = loadPaymentInfo()
if($scope.paymentInfo.method == 'cc') {
$scope.onValidateInput('fullname', paymentInfo.payer.fullname);
$scope.onValidateInput('email', paymentInfo.payer.email);
$scope.onValidateInput('confirmEmail', $("#confirmEmail").val(), paymentInfo.payer.email);
$scope.onValidateInput('phone', paymentInfo.payer.phone);
$scope.onValidateInput('card_number', paymentInfo.pay.number);
$scope.onValidateInput('city', paymentInfo.payer.city);
$scope.onValidateInput('exp_month', paymentInfo.pay.exp_month);
$scope.onValidateInput('exp_year', paymentInfo.pay.exp_year);
$scope.onValidateInput('cvc', paymentInfo.pay.cvc);
}
return true;
}
var validateDataPayment = function(){
var paymentInfo = loadPaymentInfo();
if(paymentInfo.products.length == 0 ){
return {
error : { message : "Debe incluir almenos un producto en el regalo" }
};
}
if(!paymentInfo.message || !paymentInfo.message.message || !paymentInfo.message.tel){
return {
error : { message : "Debe completar los datos del mensaje" }
};
}
var msg = paymentInfo.message;
if( !msg.emails || msg.emails.length == 0 || !lodash.every(msg.emails,'text') ){
return {
error : { message : "Debe completar los datos del mensaje, debe incluir almenos un correo" }
};
}
if(!msg.givers || msg.givers.length == 0 || !lodash.every(msg.givers, 'text')){
return {
error : { message : "Debe completar los datos del mensaje, debe incluir almenos un nombre" }
};
}
return {};
};
function callMercado(paymentInfo, orderId){
lodash.forEach($scope.mercadoMedios, function (medio) {
if (medio.elements){
lodash.forEach(medio.elements, function(item){
if (item.id === paymentInfo.mercado.pay_type){
paymentInfo.mercado.name = item.name;
$scope.methodName = item.name;
}
});
}
});
var $promise = Guest.makeMercadoPagoPayment({paymentInfo: paymentInfo, orderId: $localStorage.orderId})
.$promise
.then(function (order) {
console.log('callMercado = ',order);
$analytics.eventTrack('Item Purchased', {
'Payment Method': 'Mercado',
'Order ID': order.id,
'Total Amount': order.paymentData.amount,
'Total Number of Items': order.paymentData.products.length
});
getMixpanel().people.increment({
'Lifetime Acumulated': order.paymentData.amount
});
$scope.showHeader = false;
$scope.order = order;
$state.go('guest.checkout.receipt', {url: $scope.url});
delete $localStorage.cart[$scope.account.id];
delete $localStorage.paymentInfo[$scope.account.id];
delete $localStorage.orderId;
$scope.account = null;
$scope.products = [];
$scope.pay = {
month: null,
year: null
};
$scope.payer = {};
$scope.paymentInfo = {};
$scope.disabled = false;
})
.catch(function (err) {
console.log('callMercado Error ',err);
toastr.error(err.data.error.message);
$scope.disabled = false;
})
.finally(function () {
$scope.disabled = false;
});
}
var init ;
var loader = {
show: function() {
init = $interval(function() {
var imgs = $(".loader-image:visible");
if(!$(".loading-init").hasClass('hidden')) {
if(imgs.length == 5) {
$(".loader-image").addClass("hidden")
} else {
$("#loader_"+(imgs.length + 1)).removeClass("hidden")
}
}
}, 1000);
$(".loading-init").removeClass("hidden");
},
hide: function() {
$(".loading-init").addClass("hidden");
$interval.cancel(init);
}
}
$scope.setFocus = function(event) {
console.log(event);
setTimeout(function() {
$(event.currentTarget).click();
},9000);
}
this.pay = function () {
loader.show();
var paymentInfo = loadPaymentInfo();
var validate = validateDataPayment();
if(validate.error){
loader.hide();
toastr.error(validate.error.message,'Error');
return;
}
$scope.disabled = true;
var $promise;
if (paymentInfo.method === 'dp') {
Guest
.updateOrder({
paymentInfo: paymentInfo,
orderId: $localStorage.orderId,
paymentMethod: 'Manual'
}, function (order) {
$scope.order = order;
$state.go('guest.checkout.receipt', {url: $scope.url});
delete $localStorage.cart[$scope.account.id];
delete $localStorage.paymentInfo[$scope.account.id];
delete $localStorage.orderId;
$scope.account = null;
$scope.products = [];
$scope.pay = {
month: null,
year: null
};
$scope.payer = {};
$scope.paymentInfo = {};
$scope.disabled = false;
loader.hide();
});
} else if (paymentInfo.method === 'cc') {
var cartInfo = paymentInfo.pay;
Conekta.token.create({card: paymentInfo.pay}, function (token) {
paymentInfo.pay = token.id;
paymentInfo.first6 = cartInfo.number.toString().substr(0, 6);
$promise = Guest.makeCardPayment({paymentInfo: paymentInfo, orderId: $localStorage.orderId})
.$promise
.then(function (order) {
$analytics.eventTrack('Item Purchased', {
'Payment Method': 'Conekta',
'Order ID': order.id,
'Total Amount': order.paymentData.amount,
'Total Number of Items': order.paymentData.products.length
});
getMixpanel().people.increment({
'Lifetime Acumulated': order.paymentData.amount
});
$scope.showHeader = false;
$scope.order = order;
$state.go('guest.checkout.receipt', {url: $scope.url});
delete $localStorage.cart[$scope.account.id];
delete $localStorage.paymentInfo[$scope.account.id];
delete $localStorage.orderId;
$scope.account = null;
$scope.products = [];
$scope.pay = {
month: null,
year: null
};
$scope.payer = {};
$scope.paymentInfo = {};
$scope.disabled = false;
loader.hide();
})
.catch(function (err) {
loader.hide();
toastr.error(err.data.error.message_to_purchaser);
})
.finally(function () {
$scope.disabled = false;
});
}, function (err) {
loader.hide();
toastr.error(err.message_to_purchaser);
$scope.disabled = false;
});
} else if (paymentInfo.method === 'ox') {
$promise = Guest.makeOxxoPayment({
paymentInfo: paymentInfo,
orderId: $localStorage.orderId
})
.$promise
.then(function (order) {
$analytics.eventTrack('Item Purchased', {
'Payment Method': 'OXXO',
'Order ID': order.id,
'Total Amount': order.paymentData.amount,
'Total Number of Items': order.paymentData.products.length
});
getMixpanel().people.increment({
'Lifetime Acumulated': order.paymentData.amount
});
$scope.showHeader = false;
$scope.order = order;
$state.go('guest.checkout.receipt', {url: $scope.url});
delete $localStorage.cart[$scope.account.id];
delete $localStorage.paymentInfo[$scope.account.id];
delete $localStorage.orderId;
$scope.account = null;
$scope.products = [];
$scope.pay = {
month: null,
year: null
};
$scope.payer = {};
$scope.paymentInfo = {};
$scope.disabled = false;
loader.hide();
})
.catch(function (err) {
toastr.error(err.data.error.message_to_purchaser);
})
.finally(function () {
$scope.disabled = false;
});
}
else if (paymentInfo.method === 'mercado') {
console.log('Mercado pago request = ', paymentInfo);
var createCard = 0;
if (paymentInfo.mercado.method === 'credit_card' || paymentInfo.mercado.method === 'debit_card' || paymentInfo.mercado.method === 'prepaid_card' ){
createCard = {
email : paymentInfo.payer.email,
cardNumber : paymentInfo.pay.number,
securityCode : paymentInfo.pay.cvc,
cardExpirationMonth : paymentInfo.pay.exp_month,
cardExpirationYear : paymentInfo.pay.exp_year,
cardholderName : paymentInfo.pay.name
};
console.log('Object to create = ' , createCard);
}
if (createCard != 0){
Mercadopago.clearSession();
Mercadopago.createToken(createCard, function(status, response){
if (status != 200 && status != 201) {
$translate('mercado_'+response.cause[0].code).then(function (translation) {
toastr.error(translation);
});
$scope.disabled = false;
}else{
paymentInfo.first6 = paymentInfo.pay.number.toString().substr(0, 6);
paymentInfo.pay = response.id;
console.log('Todo Bien!!!');
callMercado(paymentInfo, localStorage.orderId );
}
});
} else {
callMercado(paymentInfo, localStorage.orderId );
}
}
else {
Guest.makePaypalPayment({paymentInfo: paymentInfo, orderId: $localStorage.orderId})
.$promise
.then(function (data) {
window.location.href = data.url;
})
.catch(function (data) {
if (data.data.error.httpStatusCode === 400) {
var err = data.data.error.response.details;
lodash.forEach(err, function (e) {
toastr.error(e.issue);
});
}
})
.finally(function () {
loader.hide();
$scope.disabled = false;
});
}
};
$scope.$on('$stateChangeSuccess', function () {
if ($state.is("guest.checkout.receipt") && !$scope.order) {
return $state.go('guest', {url: $stateParams.url});
}
if (account.isDisabled) {
return $state.go('guest', {url: $stateParams.url});
}
$scope.account = account;
var cart = $localStorage.cart;
var paymentInfo = $localStorage.paymentInfo;
var weddingCart = [];
if (!cart) {
cart = $localStorage.cart = {};
$localStorage.cartUrls = {};
} else {
weddingCart = cart[account.id];
if (!weddingCart && $state.$current.name !== 'guest.checkout.receipt') {
$translate('dont-have-items').then(function (translation) {
return toastr.info(translation);
});
return $state.go('guest.registry');
}
lodash.some(cart, function (val, key) {
$rootScope.cartUrl = $localStorage.cartUrls[key].url;
return $rootScope.cartId = key;
});
$rootScope.totalCart = weddingCart.length;
}
if (!paymentInfo) {
paymentInfo = $localStorage.paymentInfo = {method: 'cc'};
}
if (!$localStorage.cartUrls[account.id]) {
$localStorage.cartUrls[account.id] = {};
}
$localStorage.cartUrls[account.id].url = account.url;
var currentPayment = paymentInfo[account.id];
if (!currentPayment) {
currentPayment = paymentInfo[account.id] = {};
}
$scope.products = weddingCart;
$scope.paymentInfo = currentPayment;
if (!currentPayment.pay) {
currentPayment.pay = {
month: null,
year: null
}
}
if (!currentPayment.payer) {
currentPayment.payer = {
country: 'MX'
};
}
if (!currentPayment.message) {
currentPayment.message = {
emails: [],
names: []
};
}
if ($state.current.name === 'guest.checkout.pay') {
if ($localStorage.orderId) {
$scope.orderId = $localStorage.orderId;
}
else {
paymentInfo = loadPaymentInfo();
paymentInfo.urlRegistry = account.url;
Guest
.createOrder({paymentInfo: paymentInfo})
.$promise
.then(function (order) {
$scope.orderId = $localStorage.orderId = order.id;
});
}
}
});
$scope.$watch(function () {
return $scope.paymentInfo ? JSON.stringify($scope.paymentInfo) : null;
}, function (newVal) {
if (!$state.is('guest.checkout.order') && !$state.is('guest.checkout.pay')) {
if (newVal && $localStorage.orderId) {
Guest
.updateOrder({
paymentInfo: loadPaymentInfo(),
orderId: $localStorage.orderId
})
.$promise
.then(function(result){
},function(err){
if(err && err.data && err.data.error && err.data.error.message){
toastr.error(err.data.error.message,'Error');
}
});
}
}
});
}
SuccessOrderController.$inject = ['$scope', '$state', '$stateParams', '$location', 'Guest', '$localStorage', '$timeout', '$analytics', '$translate', 'toastr'];
function SuccessOrderController($scope, $state, $stateParams, $location, Guest, $localStorage, $timeout, $analytics, $translate, toastr) {
$scope = $scope.$parent;
$scope.showHeader = false;
var search = $location.search();
var params = $stateParams.orderId ? $stateParams.orderId.split("&paymentId=") : [];
if(params.length == 2) {
$stateParams.orderId = params[0];
search.paymentId = params[1];
}
Guest.confirmPaypalPayment({
orderId: $stateParams.orderId,
paymentId: search.paymentId,
token: search.token,
payerID: search.PayerID
})
.$promise
.then(function (order) {
$analytics.eventTrack('Item Purchased', {
'Payment Method': 'Paypal',
'Order ID': order.id
});
$translate('success-payment').then(function (translation) {
toastr.success(translation);
});
$scope.order = order;
$state.go('guest.checkout.receipt', {url: $scope.url});
delete $localStorage.cart[$scope.account.id];
delete $localStorage.paymentInfo[$scope.account.id];
delete $localStorage.orderId;
$scope.account = null;
$scope.products = [];
$scope.pay = {
month: null,
year: null
};
$scope.payer = {};
$scope.paymentInfo = {};
$scope.disabled = false;
});
}
})(angular.module('uniko.guest.checkout'));