Commit 4cee35f0 authored by Juorder Antonio's avatar Juorder Antonio

add app sales integrated with manager zbox app, only for global admin, for...

add app sales integrated with manager zbox app, only for global admin, for testing purposes, add sales view. etc
parent e315728f
1466617142
1467382402
\ No newline at end of file
......@@ -58,12 +58,12 @@ stop-server:
kill $$PROCID; \
done
@for PROCID in $$(ps -ef | grep "[b]abel-node.*companies" | awk '{ print $$2 }'); do \
echo stopping server $$PROCID; \
kill $$PROCID; \
done
@for PROCID in $$(ps -ef | grep "[b]abel-node.*sales" | awk '{ print $$2 }'); do \
echo stopping server $$PROCID; \
kill $$PROCID; \
done
start-server:
@echo Starting ZBox Manager 2.0 Test Server
@npm run server &
@npm run companies-service &
@npm run sales-service &
......@@ -75,6 +75,7 @@
"run": "webpack --progress --watch",
"run-fullmap": "webpack --progress --watch",
"companies-service": "babel-node companies-service.js",
"server": "babel-node server.js"
"server": "babel-node server.js",
"sales-service": "babel-node sales-services.js"
}
}
module.exports = {"main":{"js":"/419997bundle.js"}}
\ No newline at end of file
module.exports = {"main":{"js":"/312387bundle.js"}}
\ No newline at end of file
/**
* Created by enahum on 4/25/16.
*/
const http = require('http');
const express = require('express');
const cors = require('cors');
const path = require('path');
const fs = require('fs');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const Promise = require('bluebird');
const _ = require('lodash');
const moment = require('moment');
const port = normalizePort(process.env.PORT || '3300'); //eslint-disable-line no-process-env
const app = express();
app.set('port', port);
app.use(cors());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.get('/list', (req, res) => {
readSales().
then((data) => {
return res.json(data);
}).
catch((err) => {
return res.status(500).json(err);
});
});
app.post('/prices/mailboxes', (req, res) => {
const data = req.body;
const domainId = data.domainId;
readSales().then((data) => {
const prices = _.find(data, {domainId: domainId});
if (prices) {
return res.json(prices);
}
return res.status(404).json({
code: 404,
message: 'DomaindId ' + domainId + ' not found'
});
}).catch((err) => {
return res.status(500).json(err);
});
});
/*app.get('/sales/prices', (req, res) => {
return res.json([
{
number: 355,
link: 'http://google.com',
date: moment('2016-01-01').toJSON(),
total: '235581',
status: 1
},
{
number: 356,
link: 'http://google.com',
date: moment('2016-02-01').toJSON(),
total: '27581',
status: 2
},
{
number: 357,
date: moment('2016-02-01').toJSON(),
total: '30581',
status: 3
},
{
number: 358,
link: 'http://google.com',
date: moment('2016-03-01').toJSON(),
total: '35581',
status: 0
}
]);
});*/
// catch 404 and forward to error handler
app.use((req, res, next) => {
const err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use((err, req, res) => {
res.status(err.status || 500);
res.json({
message: err.message,
error: err
});
});
}
/**
* Create HTTP server.
*/
const server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
const p = parseInt(val, 10);
if (isNaN(p)) {
// named pipe
return val;
}
if (p >= 0) {
// port number
return p;
}
return false;
}
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges'); //eslint-disable-line no-console
process.exit(1); //eslint-disable-line no-process-exit
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use'); //eslint-disable-line no-console
process.exit(1); //eslint-disable-line no-process-exit
break;
default:
throw error;
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
const addr = server.address();
const bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port;
console.info('ZBox Sales Test Server listening on ' + bind); //eslint-disable-line no-console
}
function readSales() {
return new Promise((resolve, reject) => {
const filename = path.join(__dirname, 'sales', 'sales.json');
fs.readFile(filename, (err, data) => {
if (err) {
return reject(err);
}
return resolve(JSON.parse(data));
});
});
}
[
{
"domainId": "fda37354-fbec-47f5-bb26-383cf2ffe7a2",
"currency": "CLP",
"prices": {
"basic": 1.490,
"professional": 1.990,
"premium": 3.490
}
},
{
"domainId": "3d450d43-54b9-401d-bc48-a77f80baf152",
"currency": "CLP",
"prices": {
"basic": 1.490,
"professional": 1.990,
"premium": 3.490
}
},
{
"domainId": null,
"currency": "CLP",
"prices": {
"basic": 20.000,
"professional": 23.000,
"premium": 40.000
}
},
{
"domainId": null,
"currency": "CLP",
"prices": {
"basic": 20.000,
"professional": 23.000,
"premium": 40.000
}
},
{
"domainId": null,
"currency": "CLP",
"prices": {
"basic": 20.000,
"professional": 23.000,
"premium": 40.000
}
}
]
......@@ -7,6 +7,7 @@ import MessageBar from '../message_bar.jsx';
import Panel from '../panel.jsx';
import ZimbraStore from '../../stores/zimbra_store.jsx';
import UserStore from '../../stores/user_store.jsx';
import * as Utils from '../../utils/utils.jsx';
......@@ -47,6 +48,7 @@ export default class DomainMailboxPlans extends React.Component {
}
const headerButtons = [
{
label: 'Ver casillas',
props: {
......@@ -63,6 +65,18 @@ export default class DomainMailboxPlans extends React.Component {
}
];
if (UserStore.isGlobalAdmin()) {
headerButtons.unshift(
{
label: 'Comprar Casillas',
props: {
className: 'btn btn-info btn-xs',
onClick: (e) => Utils.handleLink(e, `/sales/${this.props.params.id}/mailboxes`, this.props.location)
}
}
);
}
const mailboxPlans = [];
let panelBody = null;
const cos = Utils.getEnabledPlansByCosId(ZimbraStore.getAllCos());
......
......@@ -14,6 +14,7 @@ import EventStore from '../../stores/event_store.jsx';
import MailboxStore from '../../stores/mailbox_store.jsx';
import DomainStore from '../../stores/domain_store.jsx';
import ZimbraStore from '../../stores/zimbra_store.jsx';
import UserStore from '../../stores/user_store.jsx';
import Constants from '../../utils/constants.jsx';
......@@ -267,10 +268,53 @@ export default class CreateMailBox extends React.Component {
});
}
handleRadioChanged(val) {
this.setState({
zimbraCOSId: val
});
handleRadioChanged(e, val) {
const {enabledAccounts} = this.state;
let needToBuy = false;
let data = {};
if (enabledAccounts) {
const keys = Object.keys(enabledAccounts);
keys.forEach((pos) => {
if (enabledAccounts[pos].cosId === val && enabledAccounts[pos].enabled < 1) {
needToBuy = true;
data = enabledAccounts[pos];
}
});
}
if (!needToBuy) {
return this.setState({
zimbraCOSId: val
});
}
e.target.checked = false;
const {zimbraCOSId} = this.state;
if (zimbraCOSId.length > 0) {
this.setState({
zimbraCOSId: ''
});
}
if (UserStore.isGlobalAdmin()) {
const options = {
title: 'Comprar Casilla',
text: `Por ahora no tienes más cupo para crear una casilla tipo <strong>${Utils.titleCase(data.plan)}</strong>, ¿Deseas comprar más?`,
html: true,
confirmButtonText: 'Si, compraré'
};
return Utils.alertToBuy((isConfirmed) => {
if (isConfirmed) {
const {id} = this.cacheDomain;
if (id) {
return Utils.handleLink(null, `/sales/${id}/mailboxes`);
}
}
}, options);
}
}
getAllDomains() {
......@@ -422,7 +466,7 @@ export default class CreateMailBox extends React.Component {
keyPlans.forEach((plan) => {
if (plans[plan]) {
let isDisabled = null;
//let isDisabled = null;
let classCss = null;
let info = null;
let hasPlan = false;
......@@ -430,7 +474,7 @@ export default class CreateMailBox extends React.Component {
this.state.enabledAccounts.forEach((p) => {
if (plans[plan] === p.cosId) {
hasPlan = true;
isDisabled = p.enabled < 1 ? true : null;
//isDisabled = p.enabled < 1 ? true : null;
classCss = p.classCss;
info = (
<div>
......@@ -448,7 +492,7 @@ export default class CreateMailBox extends React.Component {
}
if (this.state.enabledAccounts && !hasPlan && null) {
isDisabled = true;
//isDisabled = true;
info = (
<div>
<span className='text-danger'>
......@@ -458,11 +502,11 @@ export default class CreateMailBox extends React.Component {
);
}
const disabledCss = isDisabled ? 'disabled' : '';
//const disabledCss = isDisabled ? 'disabled' : '';
const item = (
<label
className={`radio radio-info radio-inline pretty-input ${disabledCss}`}
className={'radio radio-info radio-inline pretty-input'}
key={plan}
>
<div className='pretty-radio'>
......@@ -470,10 +514,9 @@ export default class CreateMailBox extends React.Component {
type='radio'
className='pretty'
name='mailbox'
onChange={() => {
this.handleRadioChanged(plans[plan]);
onChange={(e) => {
this.handleRadioChanged(e, plans[plan]);
}}
disabled={isDisabled}
/>
<span></span>
</div>
......
This diff is collapsed.
This diff is collapsed.
......@@ -6,6 +6,16 @@
"zimbraProxy": "https://192.168.1.8:7071",
"dnsApiUrl": "http://zimbra.zboxapp.dev:3000",
"webMailUrl": "https://192.168.1.8:8443",
"salesAPI": {
"base": "http://localhost:8080/parse",
"getPrices": "/functions/getPrices",
"makeSale": "/functions/makeSale",
"appId": "salesZboxManagerApp"
},
"invoiceAPI": {
"currency": "CLP",
"requireTax": true
},
"timeoutRequest": 60000,
"dns": {
"url": "http://zimbra.zboxapp.dev:9081/powerdns_proxy",
......@@ -24,7 +34,22 @@
"statusCos": "btn-success",
"label": "Básica",
"isEnabledToEdit": true,
"forRights": true
"forRights": true,
"sales": [
{
"disabled": false
},
{
"disabled": true,
"label": "Precio",
"hasPrice": true
},
{
"disabled": true,
"label": "$",
"ref": "total"
}
]
},
"premium": {
"statusCos": "btn-primary2",
......@@ -32,13 +57,43 @@
"isEnabledToEdit": true,
"forRights": true,
"archiving": true,
"refer": "archiving"
"refer": "archiving",
"sales": [
{
"disabled": false
},
{
"disabled": true,
"label": "Precio",
"hasPrice": true
},
{
"disabled": true,
"label": "$",
"ref": "total"
}
]
},
"professional": {
"statusCos": "btn-primary",
"label": "Profesional",
"isEnabledToEdit": true,
"forRights": true
"forRights": true,
"sales": [
{
"disabled": false
},
{
"disabled": true,
"label": "Precio",
"hasPrice": true
},
{
"disabled": true,
"label": "$",
"ref": "total"
}
]
},
"default": false,
"archiving": {
......
......@@ -23,6 +23,7 @@ import EditMailBox from './components/mailbox/edit_mailbox.jsx';
import DistributionLists from './components/distribution/distribution_lists.jsx';
import EditDistributionList from './components/distribution/edit_distribution_lists.jsx';
import SearchView from './components/search/search.jsx';
import SalesForm from './components/sales/sales.jsx';
import * as Client from './utils/client.jsx';
import * as Utils from './utils/utils.jsx';
......@@ -207,6 +208,11 @@ function renderRootComponent() {
path='search/:query'
component={SearchView}
/>
<Route
path='sales/:domainId/mailboxes'
component={SalesForm}
/>
</Route>
<Route component={NotLoggedIn}>
<IndexRedirect to='login'/>
......
......@@ -1644,3 +1644,9 @@ label {
.overflow {
overflow: hidden;
}
.alert {
&.margin-bottom {
margin-bottom: 15px;
}
}
......@@ -779,3 +779,48 @@ export function deleteRecords(zoneUrl, record, success, error) {
return success(data);
});
}
export function getPrices(data, success, error) {
const appId = window.manager_config.salesAPI.appId;
const endpoints = window.manager_config.salesAPI;
const url = endpoints.base + endpoints.getPrices;
$.ajax({
url: url,
method: 'POST',
data: data,
headers: {
'X-Parse-Application-Id': appId
},
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;
const url = endpoints.base + endpoints.makeSale;
$.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);
}
});
}
......@@ -5,6 +5,7 @@ import {browserHistory} from 'react-router';
import * as GlobalActions from '../action_creators/global_actions.jsx';
import Constants from './constants.jsx';
import ZimbraStore from '../stores/zimbra_store.jsx';
import sweetAlert from 'sweetalert';
const messageType = Constants.MessageType;
......@@ -140,7 +141,10 @@ export function areMapsEqual(a, b) {
}
export function handleLink(e, path, location) {
e.preventDefault();
if (e) {
e.preventDefault();
}
if (location) {
if (`/${location.pathname}` !== path) {
GlobalActions.emitStartLoading();
......@@ -803,3 +807,37 @@ export function addEventListenerFixed(element, type, callback) {
element.addEventListener(type, callback, typeof (fixEvents[type]) !== 'undefined');
}
export function alertToBuy(callback, options) {
const defaults = {
title: 'Alerta',
type: 'info',
showCancelButton: true,
confirmButtonColor: '#DD6B55',
confirmButtonText: 'Si, continuar',
closeOnConfirm: true,
showLoaderOnConfirm: false,
animation: 'slide-from-top'
};
const optsExtended = options ? Object.assign(defaults, options) : defaults;
sweetAlert(optsExtended,
(isConfirmed) => {
if (callback && typeof callback === 'function') {
callback(isConfirmed, sweetAlert);
}
}
);
}
export function getDaysFromDate2Date(dateFrom, dateTo) {
// check if it receive and real object date or just string
const from = typeof dateFrom === 'object' ? dateFrom : new Date(dateFrom);
const to = typeof dateTo === 'object' ? dateTo : new Date(dateTo);
// get timestamp of each date and then subtract them. just get the absolute result
var timeDiff = Math.abs(from.getTime() - to.getTime());
// round to up the result, and divide result of subtract with the amount of milliseconds of one day.
var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
return diffDays;
}
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