Merge branch 'dev' of https://git.verdnatura.es/salix into dev
* 'dev' of https://git.verdnatura.es/salix: get address return province data sales person formated getRoleCustomer return object not array of object Token authenticate, solunion notification
|
@ -1,6 +1,6 @@
|
|||
<mg-ajax path="/client/api/Addresses/{{edit.params.addressId}}" actions="$ctrl.address=edit.model" options="mgEdit"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
get="true"
|
||||
url="/client/api/Addresses"
|
||||
id-field="id"
|
||||
data="$ctrl.address"
|
||||
|
@ -23,6 +23,7 @@
|
|||
<vn-textfield vn-one label="Postcode" field="$ctrl.address.postcode"></vn-textfield>
|
||||
<vn-textfield vn-one label="City" field="$ctrl.address.city"></vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
initial-data="$ctrl.address.province"
|
||||
field="$ctrl.address.provinceFk"
|
||||
url="/client/api/Provinces"
|
||||
show-field="name"
|
||||
|
|
|
@ -29,9 +29,6 @@
|
|||
value-field="id"
|
||||
select-fields="surname"
|
||||
label="Salesperson">
|
||||
<tpl-item>
|
||||
{{$parent.$parent.item.name}} {{$parent.$parent.item.surname}}
|
||||
</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
initial-data="$ctrl.client.contactChannel"
|
||||
|
|
|
@ -17,7 +17,7 @@ export default class Controller {
|
|||
isCustomer() {
|
||||
if (this.client && this.client.id) {
|
||||
this.$http.get(`/client/api/Clients/${this.client.id}/getRoleCustomer`).then(res => {
|
||||
this.canChangePassword = (res.data && res.data.length) ? res.data[0].isCustomer : false;
|
||||
this.canChangePassword = (res.data) ? res.data.isCustomer : false;
|
||||
});
|
||||
} else {
|
||||
this.canChangePassword = false;
|
||||
|
|
|
@ -25,8 +25,10 @@ export default class Watcher extends Component {
|
|||
this.copyData();
|
||||
}
|
||||
$onInit() {
|
||||
if (this.get) {
|
||||
if (this.get && this.url) {
|
||||
this.fetchData();
|
||||
} else if (this.get && !this.url) {
|
||||
throw new Error('Error: Parameter url ommitted');
|
||||
}
|
||||
}
|
||||
$onChanges(changes) {
|
||||
|
@ -39,12 +41,15 @@ export default class Watcher extends Component {
|
|||
}
|
||||
fetchData() {
|
||||
let id = this.data[this.idField];
|
||||
return new Promise((resolve, reject) => {
|
||||
// return new Promise((resolve, reject) => {
|
||||
this.$http.get(`${this.url}/${id}`).then(
|
||||
json => this.writeData(json, resolve),
|
||||
json => reject(json)
|
||||
json => {
|
||||
this.data = this.copyObject(json.data);
|
||||
this.copyData();
|
||||
}
|
||||
// json => reject(json)
|
||||
);
|
||||
});
|
||||
// });
|
||||
}
|
||||
/**
|
||||
* Submits the data and goes back in the history.
|
||||
|
|
|
@ -1,13 +1,24 @@
|
|||
var request = require('request');
|
||||
var app = require('../../../server/server');
|
||||
|
||||
module.exports = function(Client) {
|
||||
Client.remoteMethod('activate', {
|
||||
description: 'Activate or deactive client',
|
||||
accepts: {
|
||||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'Model id',
|
||||
http: {source: 'path'}
|
||||
},
|
||||
}, {
|
||||
arg: 'context',
|
||||
type: 'object',
|
||||
http: function(ctx) {
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
arg: 'active',
|
||||
type: 'boolean'
|
||||
|
@ -18,10 +29,31 @@ module.exports = function(Client) {
|
|||
}
|
||||
});
|
||||
|
||||
Client.activate = function(id, cb) {
|
||||
Client.activate = function(id, ctx, cb) {
|
||||
Client.findById(id, function(err, client) {
|
||||
if (!err) {
|
||||
if(!err) {
|
||||
Client.update({id: client.id}, {active: !client.active});
|
||||
|
||||
let filter = {where: {clientFk: client.id}, fields: ['started', 'ended']};
|
||||
|
||||
app.models.CreditClassification.findOne(filter, function(err, data) {
|
||||
let currentDate = new Date();
|
||||
|
||||
if (client.active && data.ended >= currentDate) {
|
||||
let host = ctx.req.headers.host.split(':')[0];
|
||||
var options = {
|
||||
url: `http://${host}:5000/mailer/notification/client-deactivate/${client.id}`,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
'authorization': ctx.req.headers.authorization
|
||||
},
|
||||
json: {}
|
||||
};
|
||||
request(options);
|
||||
}
|
||||
});
|
||||
|
||||
cb(null, !client.active);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -29,8 +29,17 @@ module.exports = function(Client) {
|
|||
|
||||
Client.find(filter, function(err, instances) {
|
||||
if (!err) {
|
||||
cb(null, instances[0]);
|
||||
cb(null, formatCard(instances[0]));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function formatCard(card) {
|
||||
let cardFormated = JSON.parse(JSON.stringify(card));
|
||||
cardFormated.salesPerson = {
|
||||
id: card.salesPerson().id,
|
||||
name: `${card.salesPerson().name} ${card.salesPerson().surname}`
|
||||
};
|
||||
return cardFormated;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"relation": "salesPerson",
|
||||
"scope": {
|
||||
"fields": ["id", "name"]
|
||||
"fields": ["id", "name", "surname"]
|
||||
}
|
||||
}, {
|
||||
"relation": "contactChannel",
|
||||
|
|
|
@ -22,7 +22,7 @@ module.exports = Client => {
|
|||
],
|
||||
returns: {
|
||||
arg: 'data',
|
||||
type: Boolean,
|
||||
type: 'boolean',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
|
@ -36,7 +36,7 @@ module.exports = Client => {
|
|||
const params = [id];
|
||||
Client.rawSql(query, params, callback)
|
||||
.then(response => {
|
||||
callback(null, response);
|
||||
callback(null, response[0]);
|
||||
})
|
||||
.catch(reject => {
|
||||
callback(reject, null);
|
||||
|
|
|
@ -2,7 +2,6 @@ module.exports = (Client) => {
|
|||
Client.remoteMethod('activeSalesPerson', {
|
||||
description: 'returns actives employees with salesperson role',
|
||||
accessType: 'READ',
|
||||
isStatic: true,
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
|
@ -26,7 +25,8 @@ module.exports = (Client) => {
|
|||
let limit = filter.limit || 10;
|
||||
let where = getCondition(filter.where);
|
||||
|
||||
let query = `SELECT em.id, em.name, em.surname FROM Employee em
|
||||
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}
|
||||
|
@ -35,7 +35,7 @@ module.exports = (Client) => {
|
|||
|
||||
Client.rawSql(query, [], callback)
|
||||
.then(response => {
|
||||
callback(null, response);
|
||||
callback(null, formatSalesPerson(response));
|
||||
})
|
||||
.catch(reject => {
|
||||
callback(reject, null);
|
||||
|
@ -44,19 +44,36 @@ module.exports = (Client) => {
|
|||
|
||||
function getCondition(where) {
|
||||
let out = [];
|
||||
|
||||
if(typeof where === 'object') {
|
||||
Object.keys(where).forEach((k) => {
|
||||
let value = where[k];
|
||||
if(typeof value !== 'object') {
|
||||
if (typeof value === 'number') {
|
||||
out.push(`em.${k}=${value}`);
|
||||
} else if (typeof value === 'string') {
|
||||
out.push(`em.${k}='${value}'`);
|
||||
} else {
|
||||
} 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 ')})` : '';
|
||||
}
|
||||
|
||||
return out.length ? 'AND ' + out.join(' AND ') : '';
|
||||
function formatSalesPerson (response) {
|
||||
let results = [];
|
||||
|
||||
response.forEach( person => {
|
||||
results.push({
|
||||
id: person.id,
|
||||
name: `${person.name} ${person.surname}`
|
||||
});
|
||||
});
|
||||
|
||||
return results;
|
||||
}
|
||||
};
|
|
@ -22,6 +22,18 @@ module.exports = function(Address) {
|
|||
getAddress(ctx, data, next);
|
||||
});
|
||||
|
||||
Address.beforeRemote('findById', function(ctx, modelInstance, next) {
|
||||
ctx.args.filter = {
|
||||
"include": {
|
||||
"relation": "province",
|
||||
"scope": {
|
||||
"fields": ["id", "name"]
|
||||
}
|
||||
}
|
||||
};
|
||||
next();
|
||||
});
|
||||
|
||||
function getAddress(ctx, data, next){
|
||||
var address = Address.findOne( {where: { id: data.id}}, function (err, address){
|
||||
if(address)
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"name": "CreditClassification",
|
||||
"description": "Clientes clasificados.",
|
||||
"base": "MyModel",
|
||||
"validateUpsert": true,
|
||||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number",
|
||||
"description": "Identifier"
|
||||
},
|
||||
"started": {
|
||||
"type": "date"
|
||||
},
|
||||
"ended": {
|
||||
"type": "date"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"client": {
|
||||
"type": "belongsTo",
|
||||
"model": "Client",
|
||||
"foreignKey": "clientFk"
|
||||
}
|
||||
},
|
||||
"acls": [
|
||||
{
|
||||
"accessType": "*",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "DENY"
|
||||
},
|
||||
{
|
||||
"accessType": "*",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "root",
|
||||
"permission": "ALLOW"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -74,5 +74,8 @@
|
|||
},
|
||||
"Employee": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"CreditClassification": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
var database = require('./database.js');
|
||||
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* Initialize auth
|
||||
* @param {Object} request - Request object
|
||||
* @param {Object} response - Response object
|
||||
* @param {Object} next - Next object
|
||||
*/
|
||||
init: function(request, response, next) {
|
||||
this.request = request;
|
||||
this.response = response;
|
||||
this.next = next;
|
||||
|
||||
this.validateToken();
|
||||
},
|
||||
|
||||
/**
|
||||
* Validate auth token
|
||||
*/
|
||||
validateToken: function() {
|
||||
let query = 'SELECT userId, ttl, created FROM salix.AccessToken WHERE id = ?';
|
||||
|
||||
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 (this.isTokenExpired(token.created, token.ttl))
|
||||
return this.response.status(401).send({status: 'REJECT', data: {message: 'Token expired'}});
|
||||
|
||||
this.request.userId = token.userId;
|
||||
|
||||
this.next();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Get request token
|
||||
* @return {String} Token
|
||||
*/
|
||||
getToken: function() {
|
||||
return this.request.headers.authorization;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks if the token has expired
|
||||
* @param {String} created - Creation date
|
||||
* @param {Integer} ttl - Ttl seconds
|
||||
* @return {Boolean} True if the token has expired
|
||||
*/
|
||||
isTokenExpired: function(created, ttl) {
|
||||
let date = new Date(created);
|
||||
let currentDate = new Date();
|
||||
|
||||
date.setSeconds(date.getSeconds() + ttl);
|
||||
|
||||
if (currentDate > date)
|
||||
return true;
|
||||
}
|
||||
};
|
|
@ -3,10 +3,12 @@
|
|||
"port": 465,
|
||||
"secure": true,
|
||||
"auth": {
|
||||
"id": 10240,
|
||||
"user": "noreply",
|
||||
"pass": ""
|
||||
},
|
||||
"tls": {
|
||||
"rejectUnauthorized": false
|
||||
}
|
||||
},
|
||||
"pool": true
|
||||
}
|
|
@ -3,7 +3,7 @@ var settings = require('./settings.js');
|
|||
var path = require('path');
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
/**
|
||||
* Returns template locale
|
||||
* @param {String} template - Template name
|
||||
* @param {String} countryCode - Language code
|
||||
|
@ -25,5 +25,18 @@ module.exports = {
|
|||
cb({status: 'ACCEPT', data: {locale: require(localeFile)}});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse locale text
|
||||
* @param {String} text - Locale text
|
||||
* @param {Object} params - Locale params
|
||||
* @return {String} - Returns parsed text
|
||||
*/
|
||||
parseText: function(text, params) {
|
||||
for (var key in params) {
|
||||
text = text.replace(`%${key}%`, params[key]);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,9 +2,9 @@ var express = require('express');
|
|||
var router = new express.Router();
|
||||
var mail = require('../mail.js');
|
||||
var database = require('../database.js');
|
||||
|
||||
var settings = require('../settings.js');
|
||||
// Single user notification
|
||||
router.post('/:recipient/noticeUserSend', function(request, response) {
|
||||
/* router.post('/:recipient/noticeUserSend', function(request, response) {
|
||||
var params = {
|
||||
recipient: request.params.recipient,
|
||||
sender: request.body.sender,
|
||||
|
@ -21,14 +21,14 @@ router.post('/:recipient/noticeUserSend', function(request, response) {
|
|||
WHERE c.keyName = ? AND s.userFk = ?`;
|
||||
|
||||
database.pool.query(query, [params.category, params.recipient, params.sender], (error, result) => {
|
||||
mail.sendWithTemplate('notice', params, result => {
|
||||
mail.sendWithTemplate('notification-notice', params, result => {
|
||||
return response.json(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
}); */
|
||||
|
||||
// Send notification to all user subscribed to category
|
||||
router.post('/:category/noticeCategorySend', function(request, response) {
|
||||
/* router.post('/:category/noticeCategorySend', function(request, response) {
|
||||
var params = {
|
||||
sender: request.body.sender,
|
||||
category: request.params.category,
|
||||
|
@ -42,23 +42,38 @@ router.post('/:category/noticeCategorySend', function(request, response) {
|
|||
result.forEach(function(user) {
|
||||
params.recipient = user.id;
|
||||
|
||||
mail.sendWithTemplate('notice', params, result => {
|
||||
mail.sendWithTemplate('notification-notice', params, result => {
|
||||
return response.json(result);
|
||||
});
|
||||
}, this);
|
||||
});
|
||||
});
|
||||
}); */
|
||||
|
||||
// Send system notification
|
||||
router.post('/:recipient/noticeSystemSend', function(request, response) {
|
||||
/* router.post('/:recipient/noticeSystemSend', function(request, response) {
|
||||
var params = {
|
||||
recipient: request.params.recipient,
|
||||
sender: 50069, // verdnatura
|
||||
sender: settings.smtp().auth.id,
|
||||
category: request.body.category,
|
||||
message: request.body.message
|
||||
};
|
||||
|
||||
mail.sendWithTemplate('notice', params, result => {
|
||||
mail.sendWithTemplate('notification-notice', params, result => {
|
||||
return response.json(result);
|
||||
});
|
||||
}); */
|
||||
|
||||
// Send notification to alias solunion on client deactivate
|
||||
router.post('/client-deactivate/:clientId', function(request, response) {
|
||||
var params = {
|
||||
alias: 'solunion',
|
||||
code: 'clientDeactivate',
|
||||
bodyParams: {
|
||||
clientId: request.params.clientId
|
||||
}
|
||||
};
|
||||
|
||||
mail.sendWithTemplate('notification-alias', params, result => {
|
||||
return response.json(result);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -13,9 +13,9 @@ module.exports = {
|
|||
* @param {Object} cb - Callback
|
||||
*/
|
||||
get: function(template, params, cb) {
|
||||
var templatePath = path.join(__dirname, 'template', `${template}`, `${template}.html`);
|
||||
var templatePath = path.join(__dirname, 'template', `${template}`, `index.html`);
|
||||
var classPath = path.join(__dirname, 'template', `${template}`, `${template}.js`);
|
||||
var stylePath = path.join(__dirname, 'template', `${template}`, `${template}.css`);
|
||||
var stylePath = path.join(__dirname, 'template', `default`, `style.css`);
|
||||
|
||||
fs.stat(templatePath, (error, stat) => {
|
||||
if (error)
|
||||
|
@ -26,9 +26,13 @@ module.exports = {
|
|||
|
||||
let getRenderedStyles = body => {
|
||||
this.renderStyles(stylePath, body, body => {
|
||||
var titleSubject = body.match(new RegExp('<title>(.*?)</title>', 'i'))[1];
|
||||
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: titleSubject, body: body, attachments: attachments}});
|
||||
cb({status: 'ACCEPT', data: {recipient: instance.recipient, subject: params.subject, body: body, attachments: attachments}});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -99,7 +103,7 @@ module.exports = {
|
|||
|
||||
for (var i = 0; i < tplAttachments.length; i++) {
|
||||
var name = tplAttachments[i].replace('src="cid:', '').replace('"', '');
|
||||
var attachmentPath = path.join(__dirname, 'template/image', name);
|
||||
var attachmentPath = path.join(__dirname, 'template/default/image', name);
|
||||
|
||||
attachments.push({filename: name, path: attachmentPath, cid: name});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"subject": "Cambios en las condiciones de pago",
|
||||
"title": "Cambio en las condiciones",
|
||||
"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.",
|
||||
"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",
|
||||
"privacy": "- AVISO - Este mensaje es privado y confidencial, y debe ser utilizado exclusivamente por la persona destinataria del mismo. Si usted ha recibido este mensaje por error, le rogamos lo comunique al remitente y borre dicho mensaje y cualquier documento adjunto que pudiera contener. Verdnatura Levante SL no renuncia a la confidencialidad ni a ningún privilegio por causa de transmisión errónea o mal funcionamiento. Igualmente no se hace responsable de los cambios, alteraciones, errores u omisiones que pudieran hacerse al mensaje una vez enviado.",
|
||||
"privacyLaw": "En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal, le comunicamos que los datos personales que facilite se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L., pudiendo en todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, comunicándolo por escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación."
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
};
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
@ -0,0 +1,74 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<title>{{_.subject}}</title>
|
||||
<meta charset="utf8"/>
|
||||
</head>
|
||||
<body>
|
||||
<div style="width: 600px;margin: 0 auto;font-family: arial, sans-serif;font-size: 16px;color: #555">
|
||||
<!-- Banner block -->
|
||||
<div>
|
||||
<a href="https://www.verdnatura.es"/><img src="cid:header.png" alt="VerdNatura" style="margin:0"/></a>
|
||||
</div>
|
||||
<!-- Banner block end -->
|
||||
|
||||
<!-- Title block -->
|
||||
<div style="padding: 35px 0;background-color:#95d831;text-align: center">
|
||||
<h1 style="margin: 0;font-size: 32px;color: #333;">{{_.title}}</h1>
|
||||
</div>
|
||||
<!-- Title block end -->
|
||||
|
||||
<!-- Mail body block -->
|
||||
<div style="padding: 20px 0">
|
||||
<p style="text-align: justify">{{_.hello}}, <strong>#{{alias}}</strong></p>
|
||||
<p style="text-align: justify;font-size: 22px">{{message}}<p>
|
||||
</div>
|
||||
<!-- Mail body block end -->
|
||||
|
||||
<!-- Action button block -->
|
||||
<div style="background-color: #333;overflow:hidden">
|
||||
<a href="https://www.verdnatura.es" target="_blank" style="display:block;float:left;width:300px;height:72px;color:#fff;font-size:22px;text-decoration:none">
|
||||
<div style="float:left;width:230px;padding:22px 0;height:72px;text-align:center">{{_.actionButton}}</div>
|
||||
<div style="background-color:#95d831;text-align:center;float:right;padding-top:22px;height:50px;width:70px"><img style="margin:0" src="cid:action.png"/></div>
|
||||
</a>
|
||||
|
||||
<a href="https://goo.gl/forms/j8WSL151ZW6QtlT72" target="_blank" style="display:block;float:left;width:300px;height:72px;color:#fff;font-size:22px;text-decoration:none">
|
||||
<div style="float:left;width:230px;padding:22px 0;height:72px;text-align:center">{{_.infoButton}}</div>
|
||||
<div style="background-color:#95d831;text-align:center;float:right;padding-top:22px;height:50px;width:70px"><img style="margin:0" src="cid:info.png"/></div>
|
||||
</a>
|
||||
</div>
|
||||
<!-- Action button block end-->
|
||||
|
||||
<!-- Networks block -->
|
||||
<div style="padding:20px 0;background-color:#555;text-align:center">
|
||||
<a href="https://www.facebook.com/Verdnatura" target="_blank" style="text-decoration:none;margin-right: 10px">
|
||||
<img src="cid:facebook.png" alt="Visita nuestro Facebook" style="margin:0"/>
|
||||
</a>
|
||||
<a href="https://www.twitter.com/Verdnatura" target="_blank" style="text-decoration:none;margin-right: 10px">
|
||||
<img src="cid:twitter.png" alt="Visita nuestro Twitter" style="margin:0"/>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/Verdnatura" target="_blank" style="text-decoration:none;margin-right: 10px">
|
||||
<img src="cid:youtube.png" alt="Visita nuestro canal de Youtube" style="margin:0"/>
|
||||
</a>
|
||||
<a href="https://www.pinterest.com/Verdnatura" target="_blank" style="text-decoration:none;margin-right: 10px">
|
||||
<img src="cid:pinterest.png" alt="Visita nuestro Pinterest" style="margin:0"/>
|
||||
</a>
|
||||
<a href="https://www.instagram.com/Verdnatura" target="_blank" style="text-decoration:none;margin-right: 10px">
|
||||
<img src="cid:instagram.png" alt="Visita nuestro Instagram" style="margin:0"/>
|
||||
</a>
|
||||
<a href="https://www.linkedin.com/company/verdnatura" target="_blank" style="text-decoration:none;margin-right: 10px">
|
||||
<img src="cid:linkedin.png" alt="Visita nuestro Linkedin" style="width:50px;margin:0"/>
|
||||
</a>
|
||||
</div>
|
||||
<!-- Networks block end -->
|
||||
|
||||
<!-- Privacy block -->
|
||||
<div style="padding:20px 0;font-size:10px;font-weight:100">
|
||||
<p style="text-align: justify">{{_.fiscalAddress}}</p>
|
||||
<p style="text-align: justify">{{_.privacy}}</p>
|
||||
<p style="text-align: justify">{{_.privacyLaw}}</p>
|
||||
</div>
|
||||
<!-- Privacy block end -->
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"subject": "Has recibido una nueva notificación",
|
||||
"title": "Nueva notificación",
|
||||
"hello": "Hola",
|
||||
"notificationCode": {
|
||||
"clientDeactivate": {
|
||||
"subject": "Gestionar baja de contrato",
|
||||
"message": "El cliente con id %clientId% está clasificado, por favor, gestione la baja del contrato primero."
|
||||
}
|
||||
},
|
||||
"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",
|
||||
"privacy": "- AVISO - Este mensaje es privado y confidencial, y debe ser utilizado exclusivamente por la persona destinataria del mismo. Si usted ha recibido este mensaje por error, le rogamos lo comunique al remitente y borre dicho mensaje y cualquier documento adjunto que pudiera contener. Verdnatura Levante SL no renuncia a la confidencialidad ni a ningún privilegio por causa de transmisión errónea o mal funcionamiento. Igualmente no se hace responsable de los cambios, alteraciones, errores u omisiones que pudieran hacerse al mensaje una vez enviado.",
|
||||
"privacyLaw": "En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal, le comunicamos que los datos personales que facilite se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L., pudiendo en todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, comunicándolo por escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación."
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
var path = require('path');
|
||||
var database = require(path.join(__dirname, '../../database.js'));
|
||||
var locale = require(path.join(__dirname, '../../locale.js'));
|
||||
|
||||
module.exports = class NotificationAlias {
|
||||
getData(params, cb) {
|
||||
this.params = params;
|
||||
|
||||
let query = `SELECT alias, CONCAT(alias, '@verdnatura.es') AS recipient
|
||||
FROM account.mailAlias
|
||||
WHERE alias = ?`;
|
||||
|
||||
database.pool.query(query, [params.alias], (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 subject() {
|
||||
return this._.notificationCode[this.params.code].subject;
|
||||
}
|
||||
|
||||
get message() {
|
||||
return locale.parseText(this._.notificationCode[this.params.code].message, this.params.bodyParams);
|
||||
}
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
[]
|
|
@ -1,7 +1,7 @@
|
|||
var path = require('path');
|
||||
var database = require(path.join(__dirname, '../../database.js'));
|
||||
|
||||
module.exports = class Notice {
|
||||
module.exports = class NotificationNotice {
|
||||
getData(params, cb) {
|
||||
let query = `SELECT
|
||||
LOWER(ct.code) countryCode,
|
|
@ -0,0 +1,80 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<title>{{_.subject}}</title>
|
||||
<meta charset="utf8"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<div class="container">
|
||||
<!-- Banner block -->
|
||||
<div class="banner">
|
||||
<a href="https://www.verdnatura.es"/><img src="cid:header.png" alt="VerdNatura"/></a>
|
||||
</div>
|
||||
<!-- Banner block end -->
|
||||
|
||||
<!-- Title block -->
|
||||
<div class="title">
|
||||
<h1>{{_.title}}</h1>
|
||||
</div>
|
||||
<!-- Title block end -->
|
||||
|
||||
<!-- Mail body block -->
|
||||
<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}}}
|
||||
</p>
|
||||
<p style="text-align: justify">{{paymentAdvice}}</p>
|
||||
<p style="text-align: justify">{{_.notifyError}}</p>
|
||||
</div>
|
||||
<!-- Mail body block end -->
|
||||
|
||||
<!-- Action button block -->
|
||||
<div class="buttons">
|
||||
<a href="https://www.verdnatura.es" target="_blank"><div class="btn">
|
||||
<span class="text">{{_.actionButton}}</span>
|
||||
<span class="icon"><img src="cid:action.png"/></span>
|
||||
</div></a><a href="https://goo.gl/forms/j8WSL151ZW6QtlT72" target="_blank"><div class="btn">
|
||||
<span class="text">{{_.infoButton}}</span>
|
||||
<span class="icon"><img src="cid:info.png"/></span>
|
||||
</div></a>
|
||||
</div>
|
||||
<!-- Action button block -->
|
||||
|
||||
<!-- Networks block -->
|
||||
<div class="footer">
|
||||
<a href="https://www.facebook.com/Verdnatura" target="_blank">
|
||||
<img src="cid:facebook.png" alt="Facebook"/>
|
||||
</a>
|
||||
<a href="https://www.twitter.com/Verdnatura" target="_blank">
|
||||
<img src="cid:twitter.png" alt="Twitter"/>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/Verdnatura" target="_blank">
|
||||
<img src="cid:youtube.png" alt="Youtube"/>
|
||||
</a>
|
||||
<a href="https://www.pinterest.com/Verdnatura" target="_blank">
|
||||
<img src="cid:pinterest.png" alt="Pinterest"/>
|
||||
</a>
|
||||
<a href="https://www.instagram.com/Verdnatura" target="_blank">
|
||||
<img src="cid:instagram.png" alt="Instagram"/>
|
||||
</a>
|
||||
<a href="https://www.linkedin.com/company/verdnatura" target="_blank">
|
||||
<img src="cid:linkedin.png" alt="Linkedin"/>
|
||||
</a>
|
||||
</div>
|
||||
<!-- Networks block end -->
|
||||
|
||||
<!-- Privacy block -->
|
||||
<div class="privacy">
|
||||
<p style="text-align: justify">{{_.fiscalAddress}}</p>
|
||||
<p style="text-align: justify">{{_.privacy}}</p>
|
||||
<p style="text-align: justify">{{_.privacyLaw}}</p>
|
||||
</div>
|
||||
<!-- Privacy block end -->
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,92 +0,0 @@
|
|||
img {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
background-color: #EEE
|
||||
}
|
||||
|
||||
.container {
|
||||
font-family: arial, sans-serif;
|
||||
max-width: 600px;
|
||||
min-width: 320px;
|
||||
font-size: 16px;
|
||||
margin: 0 auto;
|
||||
color: #555
|
||||
}
|
||||
|
||||
.banner img {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.title {
|
||||
background-color: #95d831;
|
||||
text-align: center;
|
||||
padding: 35px 0
|
||||
}
|
||||
|
||||
.title h1 {
|
||||
font-size: 32px;
|
||||
color: #333;
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.body {
|
||||
background-color:#FFF;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.buttons {
|
||||
background-color: #FFF;
|
||||
text-align: center;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.buttons a {
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
.buttons .btn {
|
||||
background-color: #333;
|
||||
min-width: 300px;
|
||||
height: 72px;
|
||||
display: inline-block;
|
||||
text-align: center
|
||||
}
|
||||
|
||||
.buttons .btn .text {
|
||||
display: inline-block;
|
||||
padding-top: 22px
|
||||
}
|
||||
|
||||
.buttons .btn .icon {
|
||||
background-color: #95d831;
|
||||
text-align: center;
|
||||
padding-top: 22px;
|
||||
float: right;
|
||||
height: 50px;
|
||||
width: 70px
|
||||
}
|
||||
|
||||
.footer {
|
||||
background-color: #555;
|
||||
text-align: center;
|
||||
padding: 20px 0
|
||||
}
|
||||
|
||||
.footer a {
|
||||
text-decoration: none;
|
||||
margin-right: 5px
|
||||
}
|
||||
|
||||
.footer a img {
|
||||
margin: 0
|
||||
}
|
||||
|
||||
.privacy {
|
||||
padding: 20px 0;
|
||||
font-size: 10px;
|
||||
font-weight: 100
|
||||
}
|
|
@ -7,26 +7,29 @@ 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');
|
||||
|
||||
// Middleware
|
||||
// Body parser middleware
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.urlencoded({extended: true}));
|
||||
|
||||
// Cargar rutas
|
||||
// Auth middleware
|
||||
var requestToken = function(request, response, next) {
|
||||
auth.init(request, response, next);
|
||||
};
|
||||
|
||||
app.use(requestToken);
|
||||
|
||||
// Load routes
|
||||
app.use('/', require('./application/router.js'));
|
||||
|
||||
app.use(function(err, req, res, next) {
|
||||
console.error(err.message);
|
||||
res.status(500).send('Something broke!');
|
||||
});
|
||||
|
||||
// Iniciar escucha del servidor
|
||||
app.start = function() {
|
||||
var listener = app.listen(settings.app().port, function() {
|
||||
var servicePath = 'http://' + listener.address().address + ':' + listener.address().port;
|
||||
mail.init();
|
||||
database.init();
|
||||
database.testEmail();
|
||||
|
||||
console.log('Web server ' + settings.app().name.toUpperCase() + ' listening at: ' + servicePath);
|
||||
console.log('Browse your REST API at: ' + servicePath + '/mailer');
|
||||
if (settings.app().debug) {
|
||||
|
|