Commit 21b45111 authored by Juorder Gonzalez's avatar Juorder Gonzalez Committed by GitHub

Merge pull request #287 from ZBoxApp/manager_performance

Manager performance
parents 914fed4c a1127cde
import React from 'react';
import PageInfo from '../page_info.jsx';
import Panel from '../panel.jsx';
import moment from 'moment';
import currencyFormatter from 'currency-formatter';
import EventStore from '../../stores/event_store.jsx';
import UserStore from '../../stores/user_store.jsx';
import * as GlobalActions from '../../action_creators/global_actions.jsx';
import * as Utils from '../../utils/utils.jsx';
import * as Client from '../../utils/client.jsx';
import ZimbraStore from '../../stores/zimbra_store.jsx';
import sweetAlert from 'sweetalert';
export default class SalesForm extends React.Component {
constructor(props) {
super(props);
this.handleSetNumbersOfMailboxes = this.handleSetNumbersOfMailboxes.bind(this);
this.getPrices = this.getPrices.bind(this);
this.onlyNumber = this.onlyNumber.bind(this);
this.buildPurchase = this.buildPurchase.bind(this);
this.confirmShipping = this.confirmShipping.bind(this);
this.getDomainInfo = this.getDomainInfo.bind(this);
this.tryAgain = this.tryAgain.bind(this);
this.cos = Utils.getEnabledPlansByCos(ZimbraStore.getAllCos());
this.plans = window.manager_config.plans;
this.keys = Object.keys(this.cos);
this.sales = {};
this.isNAN = false;
this.currency = window.manager_config.invoiceAPI.currency;
const precision = this.currency === 'CLP' ? 0 : 2;
this.currencyParams = {code: this.currency, symbol: '', precision};
this.state = {
loading: true,
errorAjax: false,
disabled: false
};
}
confirmShipping(e) {
e.preventDefault();
const plans = [];
const {domain} = this.state;
const domainId = domain.id;
const companyId = domain.attrs.businessCategory;
const adminEmail = UserStore.getCurrentUser().name;
const items = {};
const data = {
domainId,
companyId,
adminEmail,
upgrade: false,
currency: this.currency
const {name, attrs} = UserStore.getCurrentUser();
const {displayName, cn, sn} = attrs._attrs;
const state = {
disabled: true,
purchase: {},
user: {
email: name,
fullname: this.buildFullName(displayName, cn, sn)
},
domainId: props.params.domainId
};
this.keys.forEach((plan) => {
if (this.sales[plan] && this.sales[plan].quantity && this.sales[plan].quantity > 0) {
items[plan] = this.sales[plan];
items[plan].type = 'Producto';
plans.push(`${Utils.titleCase(plan)} : <strong>${this.sales[plan].quantity}</strong>`);
}
});
if (plans.length < 1) {
return EventStore.emitToast({
type: 'error',
title: 'Compra Casillas',
body: 'Debe indicar cuantas casillas desea comprar.',
options: {
timeOut: 4000,
extendedTimeOut: 2000,
closeButton: true
}
});
}
this.avoidPlans = ['archiving', 'default'];
this.plans = window.manager_config.plans;
this.messageCode = window.manager_config.messageCode;
const content = plans.join(', ');
const total = `${this.refs.total.value} ${this.currency}`;
const options = {
title: 'Confirmación',
text: `Esta seguro de realizar la compra de ${content} por un total de <strong>${total}</strong>`,
html: true,
confirmButtonText: 'Si, compraré',
confirmButtonColor: '#4EA5EC',
showLoaderOnConfirm: true,
closeOnConfirm: false
};
this.mailboxes = Object.keys(this.plans).filter((plan) => {
const isValidPlan = !this.avoidPlans.includes(plan);
Utils.alertToBuy((isConfirmed) => {
if (isConfirmed) {
data.items = items;
const requestObject = JSON.stringify(data);
Client.makeSale(requestObject, () => {
Utils.alertToBuy((isConfirmed) => {
if (isConfirmed) {
Utils.handleLink(null, `/domains/${domainId}/mailboxes/new`);
}
}, {
title: 'Compra de Casillas',
text: 'Su compra se ha realizado con éxito.',
showCancelButton: false,
confirmButtonColor: '#4EA5EC',
confirmButtonText: 'Muy bien',
type: 'success'
});
}, (error) => {
Utils.alertToBuy(() => {
return null;
}, {
title: 'Error',
text: error.message || error.error.message || 'Ha ocurrido un error desconocido.',
showCancelButton: false,
confirmButtonColor: '#4EA5EC',
confirmButtonText: 'Entiendo',
type: 'error',
closeOnConfirm: true
});
});
if (isValidPlan) {
state.purchase[plan] = 0;
}
}, options);
}
getPrices() {
const {domainId} = this.props.params || this.state.domain.name || null;
const attrs = this.state.domain.attrs;
const {zimbraCreateTimestamp} = attrs;
const {businessCategory} = attrs;
const createdDate = moment(zimbraCreateTimestamp, ['YYYYDDMM', 'YYYY-DD-MM', 'DD-MM-YYYY', 'YYYY-MM-DD']);
if (!createdDate.isValid()) {
this.setState({
disabled: true,
loading: false,
errorAjax: true
});
return EventStore.emitToast({
type: 'error',
title: 'Compras - Precios',
body: 'Ha ocurrido un error al obtener su fecha de creación de dominio.',
options: {
timeOut: 4000,
extendedTimeOut: 2000,
closeButton: true
}
});
}
const data = {
domainId,
domainCreatedDate: createdDate.format('MM/DD/Y'),
anualRenovation: true,
companyId: businessCategory,
type: 'standar',
currency: this.currency
};
Client.getPrices(data, (success) => {
this.setState({
loading: false,
disabled: false,
prices: success.result.prices,
isAnual: success.result.isAnual,
description: success.result.isAnual ? success.result.description : null
});
}, (error) => {
this.setState({
errorAjax: true,
loading: false
});
return EventStore.emitToast({
type: 'error',
title: 'Compras - Precios',
body: error.message || error.error.message || 'Ha ocurrido un error al intentar obtener los precios, vuelva a intentarlo por favor.',
options: {
timeOut: 4000,
extendedTimeOut: 2000,
closeButton: true
}
});
return isValidPlan;
});
this.state = state;
}
tryAgain(e) {
e.preventDefault();
onKeyupInput(event, label) {
const value = event.target.value;
this.setState({
loading: true,
errorAjax: false
});
this.getPrices();
this.checkAmount(label, value);
}
getDomainInfo() {
const {domainId} = this.props.params;
buildFullName(displayName, cn, sn) {
const fullname = displayName && displayName.trim() !== '' ? displayName : `${cn} ${sn}`;
Client.getDomain(domainId, (res, err) => {
if (err) {
return Utils.alertToBuy(() => {
return null;
}, {
title: 'Error',
text: err.message || err.error.message || 'Ha ocurrido un error desconocido, cuando se recuperaba la información del dominio.',
showCancelButton: false,
confirmButtonColor: '#4EA5EC',
confirmButtonText: 'Entiendo',
type: 'error',
closeOnConfirm: true
});
}
return fullname;
}
this.setState({
domain: res
});
checkAmount(label, _value) {
const value = _value || 0;
const state = this.state;
const purchase = state.purchase;
const isEnabled = this.mailboxes.some((plan) => {
const planAmount = plan === label ? value : purchase[plan];
return planAmount > 0;
});
return this.getPrices();
this.setState({
disabled: !isEnabled,
purchase: {...purchase, [label]: parseInt(value, 10)}
});
}
componentDidMount() {
GlobalActions.emitEndLoading();
this.getDomainInfo();
}
onKeydownInput(event) {
const keycode = event.keyCode || event.which;
const allows = [8, 9, 37, 39, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105];
handleSetNumbersOfMailboxes(e, id) {
if (this.isNAN) {
e.preventDefault();
return null;
if (allows.includes(keycode)) {
return true;
}
const amount = e.target.value.trim();
let totalPrice = 0;
let description = 'Nuevas Casillas ';
this.keys.forEach((plan) => {
if (this.cos[plan] === id) {
const price = this.state.prices[plan];
const size = amount.length > 0 ? parseInt(amount, 10) : 0;
const total = size ? size * price : size;
const totalFormatted = total ? currencyFormatter.format(total, this.currencyParams) : total;
this.refs[`${plan}-total`].value = totalFormatted;
description += Utils.titleCase(plan);
event.preventDefault();
return null;
}
this.sales[plan] = {
quantity: size,
description,
price,
id,
total
};
buildPurchase(purchase) {
const plans = this.plans;
const content = [];
this.mailboxes.reduce((last, current) => {
const quantity = purchase[current];
if (quantity > 0) {
const plan = plans[current];
const label = quantity > 1 ? 'casillas' : 'casilla';
last.push(`${quantity} ${label} ${plan.label}`);
}
if (this.sales[plan] && this.sales[plan].total && this.sales[plan].total > 0) {
totalPrice += this.sales[plan].total;
}
});
const currentTotal = totalPrice ? currencyFormatter.format(totalPrice, this.currencyParams) : totalPrice;
this.refs.total.value = currentTotal;
return last;
}, content);
return content;
}
onlyNumber(e) {
const key = e.keyCode;
const forbidden = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 8, 9, 37, 39];
this.isNAN = false;
if (!(forbidden.indexOf(key) > -1)) {
this.isNAN = true;
e.preventDefault();
return null;
}
transformToHTML(content) {
const list = content.join('</strong>, <strong>');
return `<p><strong>${list}</strong></p>`;
}
render() {
const plans = this.cos;
const configPlans = this.plans;
const keysPlans = this.keys;
let form = null;
let actions;
const buttons = [];
const {description, disabled} = this.state;
let descriptionText;
if (description) {
descriptionText = (
<div
key='desc-key'
className='alert alert-info margin-bottom'
>
<span
className='glyphicon glyphicon glyphicon-question-sign'
aria-hidden='true'
></span>
<span className='sr-only'>Info:</span>
{description}
</div>
);
}
if (this.state.errorAjax) {
form = (
<div
className='text-center'
key={'errorajax-loading'}
>
<i
className='fa fa-refresh fa-4x fa-fw pointer'
onClick={this.tryAgain}
>
</i>
<p>{'Intentarlo de nuevo'}</p>
</div>
);
}
confirmShipping(e) {
e.preventDefault();
const {purchase, user, domainId} = this.state;
const content = this.transformToHTML(this.buildPurchase(purchase));
let data = {
purchase,
user: user.email,
fullname: user.fullname
};
const options = {
title: 'Confirmación',
text: `Esta seguro de realizar la compra de ${content}`,
html: true,
confirmButtonText: 'Si, compraré',
confirmButtonColor: '#4EA5EC',
showLoaderOnConfirm: true,
closeOnConfirm: false
};
if (this.state.isAnual) {
buttons.push(
{
label: 'Anual',
props: {
className: 'btn btn-success btn-xs'
}
}
);
} else {
buttons.push(
{
label: 'Mensual',
props: {
className: 'btn btn-info btn-xs'
Utils.alertToBuy((isConfirmed) => {
if (isConfirmed) {
Client.getDomain(domainId, (domain, err) => {
if (err) {
return sweetAlert('Error', 'El Dominio no existe.', 'error');
}
}
);
}
if (this.state.loading) {
form = (
<div
className='text-center'
key={'prices-loading'}
>
<i className='fa fa-spinner fa-spin fa-4x fa-fw'></i>
<p>{'Cargando Precios...'}</p>
</div>
);
}
if (!this.state.loading && this.state.prices) {
const prices = this.state.prices;
const rows = keysPlans.map((plan) => {
const cosId = plans[plan];
const salesArray = configPlans[plan].sales;
const fields = salesArray.map((field, index) => {
const label = field.label || `Casillas ${Utils.titleCase(plan)}`;
const price = field.hasPrice ? currencyFormatter.format(prices[plan], this.currencyParams) : '';
const myref = field.ref ? {ref: `${plan}-${field.ref}`} : {};
return (
<div
key={`sale-input-${plan}-${index}`}
className='col-xs-4'
>
<div className='form-group'>
<div className='input-group'>
<div className='input-group-addon'>{label}</div>
<input
type='text'
className='form-control'
disabled={field.disabled}
defaultValue={price}
{...myref}
onKeyUp={(e) => {
this.handleSetNumbersOfMailboxes(e, cosId);
}}
onKeyDown={this.onlyNumber}
/>
</div>
</div>
</div>
);
const {name} = domain;
data.domain = name;
Client.requestMailboxes(data, (response) => {
const text = this.messageCode[response.messageCode];
sweetAlert('Compra éxitosa', text, 'success');
}, (error) => {
const text = this.messageCode[error.messageCode];
sweetAlert('Error', text, 'error');
});
});
}
}, options);
}
return (
<div
key={`row-fields-${plan}`}
className='row'
>
{fields}
</div>
);
});
form = (
<form key='form-container'>
{rows}
<div className='row'>
<div className='col-xs-4 pull-right'>
<div className='form-group'>
<div className='input-group'>
<div className='input-group-addon'>Total</div>
<input
type='text'
disabled={true}
className='form-control'
ref='total'
/>
<div className='input-group-addon'>{this.currency}</div>
</div>
</div>
</div>
</div>
</form>
);
actions = (
renderInputs() {
const {purchase} = this.state;
return this.mailboxes.map((input, index) => {
const plan = this.plans[input];
const value = purchase[input];
return (
<div
className='row'
key='actions-container'
key={`sale-input-${plan.label}-${index}`}
className='col-xs-4'
>
<div className='col-xs-12 text-right'>
<button className='btn btn-default'>Cancelar</button>
<button
disabled={disabled}
className='btn btn-info'
onClick={this.confirmShipping}
>Comprar</button>
<div className='form-group'>
<div className='input-group'>
<div className='input-group-addon'>{`Casilla ${plan.label}`}</div>
<input
type='text'
className='form-control'
defaultValue={value}
onKeyUp={(event) => this.onKeyupInput(event, input)}
onKeyDown={this.onKeydownInput}
/>
</div>
</div>
</div>
);
}
});
}
render() {
const {disabled} = this.state;
return (
<div>
......@@ -441,9 +182,26 @@ export default class SalesForm extends React.Component {
<div className='row'>
<div className='col-md-12 central-content'>
<Panel
btnsHeader={buttons}
children={[descriptionText, form, actions]}
/>
hasHeader={true}
title={'Selecciona la cantidad de casillas que deseas comprar.'}
>
<form key='form-container'>
<div className='row'>
{this.renderInputs()}
</div>
<div
className='row'
>
<div className='col-xs-12 text-right'>
<button
disabled={disabled}
className='btn btn-info'
onClick={this.confirmShipping}
>Comprar</button>
</div>
</div>
</form>
</Panel>
</div>
</div>
</div>
......
......@@ -75,7 +75,7 @@ function initZimbra() {
export function getClientConfig(success, error) {
return $.ajax({
url: 'https://manager-api.zboxapp.com/parse/functions/getConfigManager',
url: 'https://manager.zboxapp.com/ventas_api/parse/functions/getConfigManager',
//url: './config/config.json',
dataType: 'json',
method: 'POST',
......@@ -845,6 +845,30 @@ export function getPrices(data, success, error) {
});
}
export function requestMailboxes(data, success, error) {
const appId = window.manager_config.salesAPI.appId;
const endpoints = window.manager_config.salesAPI;
const url = endpoints.base + endpoints.requestSale;
$.ajax({
url: url,
method: 'POST',
data: data,
contentType: 'application/json',
headers: {
'X-Parse-Application-Id': appId,
'X-Parse-REST-API-Key': 'master'
},
dataType: 'json',
success: function onSuccess(response) {
success(response);
},
error: function onError(err) {
error(err.responseJSON || err);
}
});
}
export function makeSale(data, success, error) {
const appId = window.manager_config.salesAPI.appId;
const endpoints = window.manager_config.salesAPI;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment