Merge branch 'dev' of https://git.verdnatura.es/salix into dev

* 'dev' of https://git.verdnatura.es/salix:
  facke active drivers rest created
  parse vars in filer routes
  Respuesta json en peticiones, auth, escrito impresoras
This commit is contained in:
Carlos 2017-10-17 12:29:59 +02:00
commit 5073527c93
21 changed files with 293 additions and 155 deletions

View File

@ -20,7 +20,12 @@
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-one label="Driver" field="$ctrl.delivery.driver"></vn-textfield>
<vn-autocomplete vn-one
field="$ctrl.delivery.driver"
url="/route/api/Deliveries/activeDrivers"
label="Driver"></vn-autocomplete>
<vn-textfield vn-one label="Vehicle" field="$ctrl.delivery.vehicle"></vn-textfield>
</vn-horizontal>

View File

@ -53,11 +53,11 @@ module.exports = function(app) {
loginUrl = applications[apiKey];
res.send(JSON.stringify({
res.json({
token: token.id,
continue: continueUrl,
loginUrl: loginUrl
}));
});
}
function findCb(err, instance) {
if (err || !instance || instance.password !== md5(password)) {
@ -78,13 +78,14 @@ module.exports = function(app) {
}
function badLogin() {
res.status(401);
res.send(JSON.stringify({
res.json({
message: 'Login failed'
}));
});
}
});
app.get('/logout', function(req, res) {
console.log(req.accessToken);
User.logout(req.accessToken.id,
() => res.redirect('/'));
});

View File

@ -25,17 +25,13 @@ module.exports = {
database.pool.query(query, [this.getToken()], (error, result) => {
let token = result[0];
if (error)
return this.response.status(401).send({status: 'REJECT', data: {message: error.code}});
if (result.length == 0)
return this.response.status(401).send({status: 'REJECT', data: {message: 'No token found'}});
if (error || result.length == 0)
return this.response.status(401).send({message: 'Invalid token'});
if (this.isTokenExpired(token.created, token.ttl))
return this.response.status(401).send({status: 'REJECT', data: {message: 'Token expired'}});
return this.response.status(401).send({message: 'Token expired'});
this.request.userId = token.userId;
this.next();
});
},

View File

@ -17,12 +17,12 @@ module.exports = {
if (error) {
fs.stat(defaultLocaleFile, (error, stats) => {
if (error)
return cb({status: 'REJECT', data: {message: 'Translation not found for template ' + template + '.'}});
return cb(new Error('Translation not found for template ' + template));
cb({status: 'ACCEPT', data: {locale: require(defaultLocaleFile)}});
cb(null, {locale: require(defaultLocaleFile)});
});
} else {
cb({status: 'ACCEPT', data: {locale: require(localeFile)}});
cb(null, {locale: require(localeFile)});
}
});
},

View File

@ -50,12 +50,12 @@ module.exports = {
this.log(params.sender, params.recipient, recipient, subject, body, params.message, status);
if (error)
return cb({status: 'REJECT', data: {message: 'Email not sent: ' + error}});
return cb(new Error('Email not sent: ' + error));
if (settings.app().debug)
console.log('Mail sent ' + info.messageId + ' [' + info.response + ']');
cb({status: 'ACCEPT', data: {message: 'Email sent'}});
cb();
});
},
@ -66,12 +66,15 @@ module.exports = {
* @param {Object} cb - Callback
*/
sendWithTemplate: function(tplName, params, cb) {
template.get(tplName, params, result => {
if (result.status == 'REJECT')
return cb(result);
template.get(tplName, params, (error, result) => {
if (error)
return cb(error);
this.send(result.data.recipient, result.data.subject, result.data.body, result.data.attachments, params, result => {
cb(result);
this.send(result.recipient, result.subject, result.body, result.attachments, params, error => {
if (error)
return cb(error);
cb();
});
});
},

View File

@ -1,17 +1,24 @@
var express = require('express');
var router = new express.Router();
var mail = require('../mail.js');
var auth = require('../auth.js');
// Auth middleware
var requestToken = function(request, response, next) {
auth.init(request, response, next);
};
// Payment method changes
router.post('/payment-update/:clientId', requestToken, function(request, response, next) {
mail.sendWithTemplate('payment-update', {recipient: request.params.clientId}, result => {
return response.json(result);
router.post('/payment-update/:clientId', function(request, response, next) {
mail.sendWithTemplate('payment-update', {recipient: request.params.clientId}, error => {
if (error)
return response.status(400).json({message: error.message});
return response.json();
});
});
// Printer setup
router.post('/printer-setup/:clientId', function(request, response, next) {
mail.sendWithTemplate('printer-setup', {recipient: request.params.clientId}, error => {
if (error)
return response.status(400).json({message: error.message});
return response.json();
});
});

View File

@ -3,12 +3,6 @@ var router = new express.Router();
var mail = require('../mail.js');
var database = require('../database.js');
var settings = require('../settings.js');
var auth = require('../auth.js');
// Auth middleware
var requestToken = function(request, response, next) {
auth.init(request, response, next);
};
// Single user notification
/* router.post('/:recipient/noticeUserSend', function(request, response) {
@ -71,7 +65,7 @@ var requestToken = function(request, response, next) {
}); */
// Send notification to alias solunion on client deactivate
router.post('/client-deactivate/:clientId', requestToken, function(request, response) {
router.post('/client-deactivate/:clientId', function(request, response) {
var params = {
alias: 'solunion',
code: 'clientDeactivate',
@ -80,8 +74,11 @@ router.post('/client-deactivate/:clientId', requestToken, function(request, resp
}
};
mail.sendWithTemplate('notification-alias', params, result => {
return response.json(result);
mail.sendWithTemplate('notification-alias', params, error => {
if (error)
response.status(400).json({message: error.message});
return response.json();
});
});

View File

@ -4,7 +4,7 @@ var settings = require('./settings.js');
// Mailer default page
router.get('/', function(request, response) {
response.send(settings.app().name + ' v' + settings.app().version);
response.json({});
});
// Manuscripts

View File

@ -5,13 +5,13 @@ var path = require('path');
var inlineCss = require('inline-css');
module.exports = {
/**
* Obtiene la plantilla.
* @param {String} template - Nombre de la plantilla
* @param {Object} countryCode - Código del idioma
* @param {Object} params - Datos a reemplazar.
* @param {Object} cb - Callback
*/
/**
* Get template.
* @param {String} template - Template name
* @param {Object} countryCode - Language code
* @param {Object} params - Params
* @param {Object} cb - Callback
*/
get: function(template, params, cb) {
var templatePath = path.join(__dirname, 'template', `${template}`, `index.html`);
var classPath = path.join(__dirname, 'template', `${template}`, `${template}.js`);
@ -19,65 +19,68 @@ module.exports = {
fs.stat(templatePath, (error, stat) => {
if (error)
return cb(null, 'Template ' + template + ' not found');
return cb(new Error('Template ' + template + ' not found'));
let TemplateClass = require(classPath);
let instance = new TemplateClass();
let getRenderedStyles = body => {
this.renderStyles(stylePath, body, body => {
this.renderStyles(stylePath, body, (error, body) => {
params.subject = params.subject || instance.subject;
if (params.subject == undefined)
params.subject = body.match(new RegExp('<title>(.*?)</title>', 'i'))[1];
this.getAttachments(template, body, attachments => {
cb({status: 'ACCEPT', data: {recipient: instance.recipient, subject: params.subject, body: body, attachments: attachments}});
this.getAttachments(template, body, (error, attachments) => {
if (error)
return cb(error);
cb(null, {recipient: instance.recipient, subject: params.subject, body: body, attachments: attachments});
});
});
};
let getDataCb = () => {
this.render(templatePath, instance, body => getRenderedStyles(body));
this.render(templatePath, instance, (error, result) => getRenderedStyles(result));
};
instance.getData(params, result => {
if (result.status == 'REJECT')
return cb(result);
instance.getData(params, (error, result) => {
if (error)
return cb(error);
locale.load(template, instance.countryCode, result => {
if (result.status == 'REJECT')
return cb(result);
locale.load(template, instance.countryCode, (error, result) => {
if (error)
return cb(error);
instance._ = result.data.locale;
getDataCb(result);
instance._ = result.locale;
getDataCb(null, result);
});
});
});
},
/**
* Renderiza las plantillas
* @param {String} path - Ruta de la plantilla
* @param {Object} data - Listado de parámetros a remplazar
* @param {Object} cb - Callback
*/
/**
* Render template
* @param {String} path - Template path
* @param {Object} data - Params
* @param {Object} cb - Callback
*/
render: function(path, data, cb) {
fs.readFile(path, 'utf8', function(error, body) {
mustache.parse(body);
cb(mustache.render(body, data));
cb(null, mustache.render(body, data));
});
},
/**
* Renderiza los estilos de las plantillas.
* @param {String} path - Ruta de la hoja de estilos
* @param {String} body - Html renderizado
* @param {Object} cb - Callback
*/
/**
* Render template style.
* @param {String} path - Stylesheet path
* @param {String} body - Rendered html
* @param {Object} cb - Callback
*/
renderStyles: function(path, html, cb) {
fs.stat(path, error => {
if (error) return cb(null, 'Template stylesheet not found');
if (error) return cb(new Error('Template stylesheet not found'));
fs.readFile(path, 'utf8', (error, css) => {
let style = '<style>' + css + '</style>';
let body = style + html;
@ -85,42 +88,67 @@ module.exports = {
inlineCss(body, options)
.then(function(body) {
cb(body);
cb(null, body);
});
});
});
},
/**
* Obtiene todos los ficheros adjuntos de la plantilla
* @param {String} template - Nombre de la plantilla
* @param {String} body - html de la plantilla
* @param {Object} cb - Callback
*/
/**
* Get template attachments
* @param {String} template - Template name
* @param {String} body - template body
* @param {Object} cb - Callback
*/
getAttachments: function(template, body, cb) {
var attachments = [];
var tplAttachments = body.match(new RegExp('src="cid:(.*?)"', 'ig'));
let attachments = [];
let tplAttachments = body.match(new RegExp('src="cid:(.*?)"', 'ig'));
// Template default attachments
for (var i = 0; i < tplAttachments.length; i++) {
var name = tplAttachments[i].replace('src="cid:', '').replace('"', '');
var attachmentPath = path.join(__dirname, 'template/default/image', name);
let name = tplAttachments[i].replace('src="cid:', '').replace('"', '');
let attachmentPath = path.join(__dirname, 'template/default/image', name);
attachments.push({filename: name, path: attachmentPath, cid: name});
}
var attachmentsPath = path.join(__dirname, 'template', `${template}`, 'attachment.json');
// Template attachment files
let attachmentsPath = path.join(__dirname, 'template', `${template}`, 'attachment.json');
fs.stat(attachmentsPath, (error, stats) => {
if (error) return cb(null, 'Could not load attachments from template ' + template);
if (error)
return cb(new Error(`Could not load attachments.js from template ${template}`));
var attachObj = require(attachmentsPath);
let attachObj = require(attachmentsPath);
for (var i = 0; i < attachObj.length; i++) {
var attachmentPath = path.join(__dirname, 'template', `${template}`, 'attachment', attachObj[i]);
attachments.push({filename: attachObj[i], path: attachmentPath, cid: attachObj[i]});
let filename = attachObj[i];
let attachmentPath = path.join(__dirname, 'template', `${template}`, 'attachment', filename);
attachments.push({filename: filename, path: attachmentPath, cid: filename});
}
cb(attachments);
this.checkAttachments(attachments, error => {
if (error)
return cb(error);
cb(null, attachments);
});
});
},
/**
* Check all template attachments
* @param {Object} attachments - Attachments object
* @param {Object} cb - Callback
*/
checkAttachments: function(attachments, cb) {
for (var i = 0; i < attachments.length; i++) {
var attachment = attachments[i];
fs.stat(attachment.path, error => {
if (error)
return cb(new Error(`Could not load attachment file ${attachment.path}`));
});
}
cb();
}
};

View File

@ -1,41 +0,0 @@
var path = require('path');
var database = require(path.join(__dirname, '../../database.js'));
var format = require(path.join(__dirname, '../../util/format.js'));
module.exports = class PaymentUpdate {
getData(params, cb) {
let query = `SELECT
pm.id payMethodFk,
pm.name payMethodName,
c.dueDay,
c.iban,
LOWER(ct.code) countryCode,
c.email recipient
FROM client c
JOIN payMethod pm ON pm.id = c.paymentMethodFk
JOIN country ct ON ct.id = c.countryFk
WHERE c.id = ?`;
database.pool.query(query, [params.recipient], (error, result) => {
if (error || result.length == 0)
return cb({status: 'REJECT', data: {message: 'No data found', error: error}});
Object.assign(this, result[0]);
cb({status: 'ACCEPT', data: {}});
});
}
get paymentDay() {
if (this.payMethodFk != 5) {
return `<div>${this._.paymentDay}: <strong style="font-size: 16px">${this.dueDay} ${this._.everyMonth}</strong></div>`;
}
}
get paymentAdvice() {
switch (this.payMethodFk) {
case 4:
return `${this._.accountPaymentAdviceBefore} ${format.partialAccountAddress(this.iban)} ${this._.accountPaymentAdviceAfter}`;
case 5:
return this._.cardPaymentAdvice;
}
}
};

View File

@ -12,10 +12,10 @@ module.exports = class NotificationAlias {
database.pool.query(query, [params.alias], (error, result) => {
if (error || result.length == 0)
return cb({status: 'REJECT', data: {message: 'No data found', error: error}});
return cb(new Error('No template data found'));
Object.assign(this, result[0]);
cb({status: 'ACCEPT', data: {}});
cb();
});
}

View File

@ -17,10 +17,10 @@ module.exports = class PaymentUpdate {
WHERE c.id = ?`;
database.pool.query(query, [params.recipient], (error, result) => {
if (error || result.length == 0)
return cb({status: 'REJECT', data: {message: 'No data found', error: error}});
return cb(new Error('No template data found'));
Object.assign(this, result[0]);
cb({status: 'ACCEPT', data: {}});
cb();
});
}

View File

@ -0,0 +1 @@
["model.ezp"]

View File

@ -23,12 +23,49 @@
<div class="body">
<p style="text-align: justify">{{_.dear}},</p>
<p style="text-align: justify">{{_.bodyDescription}}</p>
<p style="text-align: justify">
<div>{{_.paymentMethod}}: <strong style="font-size: 16px">{{payMethodName}}</strong></div>
{{{paymentDay}}}
Puede utilizar como guía, el video del montaje del ribon y la cinta <a href="https://www.youtube.com/watch?v=qhb0kgQF3o8" title="Youtube" target="_blank" style="color:#8dba25">https://www.youtube.com/watch?v=qhb0kgQF3o8</a>.
También necesitará el QLabel, el programa para imprimir las cintas.</p>
<p>Puede descargarlo desde este enlace <a href="http://www.godexintl.com/en/product/type/Download/2967" title="Descargar QLabel" target="_blank" style="color:#8dba25">http://www.godexintl.com/en/product/type/Download/2967</a></p>
<h1 style="color:#999">Utilización de QLabel</h1>
<p style="text-align: justify">Para utilizar el programa de impresión de cintas siga estos pasos:</p>
<ol>
<li>Abra el programa QLabel.</li>
<li>Haga click en el icono de la carpeta.</li>
<li>Seleccione el archivo plantilla llamado "MODEL.ezp".</li>
<li>Haga click ENCIMA DEL TEXTO con el boton secundario del ratÓn.</li>
<li>Elija la primera opcion "SETUP".</li>
<li>Cambie el texto para imprimir.</li>
<li>Haga click en el boton OK.</li>
<li>Desplácese con el raton para ver la medida máxima.</li>
<li>Haga click ENCIMA DEL TEXTO con el boton secundario del raton.</li>
<li>Elija la primera opcion "SETUP PRINTER".</li>
<li>Haga click en la primera pestalla "Label Setup".</li>
<li>Y modifique la propidad "Paper Height".</li>
<li>Haga click en el boton OK.</li>
<li>Haga click sobre el icono de la impresora.</li>
<li>Haga click en "Print".</li>
</ol>
<h1 style="color:#999">¿Necesita ayuda?</h1>
<p style="text-align: justify">Si necesita ayuda, descárguese nuestro programa de soporte para poder conectarnos remotamente a su pc y hacerle la instalación.
Proporciónenos un horario de contacto para atenderle, y contactaremos con usted.</p>
<p>Puede descargarse el programa desde este enlace <a href="http://soporte.verdnatura.es" title="Soporte Verdnatura" target="_blank" style="color:#8dba25">http://soporte.verdnatura.es</a></p>
<p>
<div>Soy tu comercial y mi nombre es: <strong style="font-size: 20px">{{_.salesPersonName}}</strong></div>
<div>Teléfono y whatsapp: <strong style="font-size: 20px">{salesMan_phone}</strong></div>
<div>Email: <strong><a href="mailto:{salesMan_mail}" target="_blank" style="color:#8dba25;font-size: 20px">{salesMan_mail}</a></strong></div>
</p>
<p style="text-align: justify">{{paymentAdvice}}</p>
<p style="text-align: justify">{{_.notifyError}}</p>
</div>
<!-- Mail body block end -->

View File

@ -1,15 +1,8 @@
{
"subject": "Cambios en las condiciones de pago",
"title": "Cambio en las condiciones",
"subject": "Instalación y configuración de impresora",
"title": "¡GRACIAS POR SU CONFIANZA!",
"dear": "Estimado cliente",
"bodyDescription": "Le informamos que han cambiado las condiciones de pago de su cuenta. A continuación le indicamos las nuevas condiciones:",
"paymentMethod": "Método de pago",
"paymentDay": "Día de pago",
"everyMonth": "de cada mes",
"cardPaymentAdvice": "Su modo de pago actual implica que deberá abonar el importe de los pedidos realizados en el mismo día para que se puedan enviar.",
"accountPaymentAdviceBefore": "Su modo de pago actual implica que se le pasará un cargo a la cuenta",
"accountPaymentAdviceAfter": "por el importe pendiente, al vencimiento establecido en las condiciones.",
"notifyError": "En el caso de detectar algún error en los datos indicados o para cualquier aclaración, debe dirigirse a su comercial.",
"bodyDescription": "Siga las intrucciones especificadas en este correo para llevar a cabo la instalación de la impresora.",
"actionButton": "Visita nuestra Web",
"infoButton": "Ayúdanos a mejorar",
"fiscalAddress": "VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla _ www.verdnatura.es _ clientes@verdnatura.es",

View File

@ -0,0 +1,23 @@
var path = require('path');
var database = require(path.join(__dirname, '../../database.js'));
var format = require(path.join(__dirname, '../../util/format.js'));
module.exports = class PaymentUpdate {
getData(params, cb) {
let query = `SELECT
CONCAT(w.name, ' ', w.firstName) salesPersonName,
LOWER(ct.code) countryCode,
c.email recipient
FROM client c
LEFT JOIN worker w ON w.id = c.workerFk
JOIN country ct ON ct.id = c.countryFk
WHERE c.id = ?`;
database.pool.query(query, [params.recipient], (error, result) => {
if (error || result.length == 0)
return cb(new Error('No template data found'));
Object.assign(this, result[0]);
cb();
});
}
};

View File

@ -7,11 +7,19 @@ var bodyParser = require('body-parser');
var settings = require('./application/settings.js');
var mail = require('./application/mail.js');
var database = require('./application/database.js');
var auth = require('./application/auth.js');
// Body parser middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
// Auth middleware
var requestToken = function(request, response, next) {
auth.init(request, response, next);
};
app.use(requestToken);
// Load routes
app.use('/', require('./application/router.js'));

View File

@ -0,0 +1,79 @@
module.exports = (Delivery) => {
Delivery.remoteMethod('activeDrivers', {
description: 'returns actives employees with driver role',
accessType: 'READ',
accepts: [{
arg: 'filter',
type: 'Object',
required: false,
description: 'Filter defining where and paginated data',
http: {source: 'query'}
}],
returns: {
arg: 'data',
type: 'Employee',
root: true
},
http: {
path: `/activeDrivers`,
verb: 'get'
}
});
Delivery.activeDrivers = (filter, callback) => {
let skip = filter.skip || 0;
let limit = filter.limit || 10;
let where = getCondition(filter.where);
// TODO: change salesPerson role to Driver role when it will be created
let query = `SELECT em.id, em.name, em.surname
FROM Employee em
JOIN Account ac ON em.userFk = ac.id
JOIN Role ON Role.id = ac.roleFK
WHERE ac.active AND Role.\`name\`='salesPerson' ${where}
ORDER BY em.name ASC
LIMIT ${limit} OFFSET ${skip}`;
Delivery.rawSql(query, [], callback)
.then(response => {
callback(null, formatDriver(response));
})
.catch(reject => {
callback(reject, null);
});
};
function getCondition(where) {
let out = [];
if(typeof where === 'object') {
Object.keys(where).forEach((k) => {
let value = where[k];
if (typeof value === 'number') {
out.push(`em.${k}=${value}`);
} else if (typeof value === 'string') {
out.push(`em.${k}='${value}'`);
} else if (typeof value === 'boolean' || value === null) {
out.push(`em.${k} IS ${String(value).toUpperCase()}`);
} else if (Object.keys(value).length) {
let firstProperty = Object.keys(value)[0];
out.push(`em.${k} ${firstProperty} '${value[firstProperty]}'`);
} else {
throw new Error ('Error: unexpected type');
}
});
}
return out.length ? `AND (${out.join(' AND ')})` : '';
}
function formatDriver (response) {
let results = [];
response.forEach( person => {
results.push({
id: person.id,
name: `${person.name} ${person.surname}`
});
});
return results;
}
};

View File

@ -16,16 +16,16 @@ module.exports = function(Delivery) {
]
},
skip: (params.page - 1) * params.size,
limit: params.size
skip: (parseInt(params.page, 10) - 1) * parseInt(params.size, 10),
limit: parseInt(params.size, 10)
};
}
function andWhere(params) {
let filters = {
where: {},
skip: (params.page - 1) * params.size,
limit: params.size
skip: (parseInt(params.page, 10) - 1) * parseInt(params.size, 10),
limit: parseInt(params.size, 10)
};
delete params.page;

View File

@ -1,4 +1,5 @@
module.exports = function(Self) {
require('../methods/filter.js')(Self);
require('../methods/drivers.js')(Self);
};