Errores de renderización imágenes adjuntas. Escritos de cliente deutor.

This commit is contained in:
Joan Sanchez 2017-12-26 10:02:47 +01:00
parent 9e44803c66
commit e94d29f97b
116 changed files with 1245 additions and 593 deletions

View File

@ -12,7 +12,7 @@ export default class App {
this.$rootScope = $rootScope; this.$rootScope = $rootScope;
} }
show(message) { show(message) {
if (this.snackbar) this.snackbar.show({message: message}); if (this.snackbar) this.snackbar.show({message: message, timeout: 400});
} }
showMessage(message) { showMessage(message) {
this.show(message); this.show(message);

View File

@ -4,10 +4,15 @@ var config = require('../config.js');
var mail = require('../mail.js'); var mail = require('../mail.js');
var template = require('../template.js'); var template = require('../template.js');
var httpRequest = require('request'); var httpRequest = require('request');
var auth = require('../auth.js');
// Auth middleware
var requestToken = function(request, response, next) {
auth.init(request, response, next);
};
// Printer setup // Printer setup
router.post('/printer-setup/:clientId', function(request, response) { router.get('/printer-setup/:clientId', requestToken, function(request, response) {
mail.sendWithTemplate('printer-setup', {clientId: request.params.clientId}, error => { mail.sendWithTemplate('printer-setup', {clientId: request.params.clientId}, error => {
if (error) if (error)
return response.status(400).json({message: error.message}); return response.status(400).json({message: error.message});
@ -17,7 +22,7 @@ router.post('/printer-setup/:clientId', function(request, response) {
}); });
// Printer setup preview // Printer setup preview
router.get('/printer-setup/:clientId', function(request, response) { router.get('/printer-setup/:clientId/preview', requestToken, function(request, response) {
template.get('printer-setup', {clientId: request.params.clientId, isPreview: true}, (error, result) => { template.get('printer-setup', {clientId: request.params.clientId, isPreview: true}, (error, result) => {
if (error) if (error)
return response.status(400).json({message: error.message}); return response.status(400).json({message: error.message});
@ -27,7 +32,7 @@ router.get('/printer-setup/:clientId', function(request, response) {
}); });
// Client welcome // Client welcome
router.post('/client-welcome/:clientId', function(request, response) { router.get('/client-welcome/:clientId', requestToken, function(request, response) {
mail.sendWithTemplate('client-welcome', {clientId: request.params.clientId}, error => { mail.sendWithTemplate('client-welcome', {clientId: request.params.clientId}, error => {
if (error) if (error)
return response.status(400).json({message: error.message}); return response.status(400).json({message: error.message});
@ -37,7 +42,7 @@ router.post('/client-welcome/:clientId', function(request, response) {
}); });
// Client welcome preview // Client welcome preview
router.get('/client-welcome/:clientId', function(request, response) { router.get('/client-welcome/:clientId/preview', requestToken, function(request, response) {
template.get('client-welcome', {clientId: request.params.clientId, isPreview: true}, (error, result) => { template.get('client-welcome', {clientId: request.params.clientId, isPreview: true}, (error, result) => {
if (error) if (error)
return response.status(400).json({message: error.message}); return response.status(400).json({message: error.message});
@ -47,8 +52,13 @@ router.get('/client-welcome/:clientId', function(request, response) {
}); });
// Client SEPA CORE // Client SEPA CORE
router.post('/sepa-core/:clientId', function(request, response) { router.get('/sepa-core/:companyId/:clientId', requestToken, function(request, response) {
let path = `${request.proxyHost}/print/manuscript/sepa-core/${request.params.clientId}`; let params = {
clientId: request.params.clientId,
companyId: request.params.companyId
};
let path = `${request.proxyHost}/print/manuscript/sepa-core/${params.companyId}/${params.clientId}`;
let options = { let options = {
url: path, url: path,
method: 'GET', method: 'GET',
@ -59,14 +69,13 @@ router.post('/sepa-core/:clientId', function(request, response) {
let httpStream = httpRequest(options, function(error, httpResponse, body) { let httpStream = httpRequest(options, function(error, httpResponse, body) {
if (error || httpResponse.statusCode != 200) if (error || httpResponse.statusCode != 200)
return response.status(400).json({message: error.message}); return response.status(400).json({message: error});
}); });
if (httpStream) if (httpStream)
mail.sendWithTemplate('sepa-core', { params.attachments = [{filename: 'sepa-core.pdf', content: httpStream}];
clientId: request.params.clientId,
attachments: [{filename: 'sepa-core.pdf', content: httpStream}] mail.sendWithTemplate('sepa-core', params, error => {
}, error => {
if (error) if (error)
return response.status(400).json({message: error.message}); return response.status(400).json({message: error.message});
@ -75,9 +84,60 @@ router.post('/sepa-core/:clientId', function(request, response) {
}); });
// Client SEPA CORE preview // Client SEPA CORE preview
router.get('/sepa-core/:clientId', function(request, response) { router.get('/sepa-core/:companyId/:clientId/preview', requestToken, function(request, response) {
template.get('sepa-core', { let params = {
clientId: request.params.clientId, clientId: request.params.clientId,
companyId: request.params.companyId,
token: request.user.token,
isPreview: true
};
template.get('sepa-core', params, (error, result) => {
if (error)
return response.status(400).json({message: error.message});
response.send(result.body);
});
});
// First debtor letter
router.get('/letter-debtor-st/:companyId/:clientId', requestToken, function(request, response) {
let params = {
clientId: request.params.clientId,
companyId: request.params.companyId,
token: request.user.token
};
let path = `${request.proxyHost}/print/manuscript/letter-debtor/${params.companyId}/${params.clientId}`;
let options = {
url: path,
method: 'GET',
headers: {
'Authorization': request.headers.authorization
}
}
let httpStream = httpRequest(options, function(error, httpResponse, body) {
if (error || httpResponse.statusCode != 200)
return response.status(400).json({message: error});
});
if (httpStream)
params.attachments = [{filename: 'extracto.pdf', content: httpStream}];
mail.sendWithTemplate('letter-debtor-st', params, error => {
if (error)
return response.status(400).json({message: error.message});
return response.json();
});
});
// First debtor letter preview
router.get('/letter-debtor-st/:companyId/:clientId/preview', requestToken, function(request, response) {
template.get('letter-debtor-st', {
clientId: request.params.clientId,
companyId: request.params.companyId,
token: request.user.token, token: request.user.token,
isPreview: true isPreview: true
}, (error, result) => { }, (error, result) => {
@ -88,6 +148,85 @@ router.get('/sepa-core/:clientId', function(request, response) {
}); });
}); });
// Second debtor letter
router.get('/letter-debtor-nd/:companyId/:clientId', requestToken, function(request, response) {
let params = {
clientId: request.params.clientId,
companyId: request.params.companyId,
token: request.user.token
};
let path = `${request.proxyHost}/print/manuscript/letter-debtor/${params.companyId}/${params.clientId}`;
let options = {
url: path,
method: 'GET',
headers: {
'Authorization': request.headers.authorization
}
}
let httpStream = httpRequest(options, function(error, httpResponse, body) {
if (error || httpResponse.statusCode != 200)
return response.status(400).json({message: error});
});
if (httpStream)
params.attachments = [{filename: 'extracto.pdf', content: httpStream}];
mail.sendWithTemplate('letter-debtor-nd', params, error => {
if (error)
return response.status(400).json({message: error.message});
return response.json();
});
});
// Second debtor letter preview
router.get('/letter-debtor-nd/:companyId/:clientId/preview', requestToken, function(request, response) {
template.get('letter-debtor-nd', {
clientId: request.params.clientId,
companyId: request.params.companyId,
token: request.user.token,
isPreview: true
}, (error, result) => {
if (error)
return response.status(400).json({message: error.message});
response.send(result.body);
});
});
// Payment method changes
router.get('/payment-update/:clientId', requestToken, function(request, response) {
mail.sendWithTemplate('payment-update', {clientId: request.params.clientId}, error => {
if (error)
return response.status(400).json({message: error.message});
return response.json();
});
});
// Send notification to alias creditInsurance on client deactivate
router.get('/client-deactivate/:clientId', requestToken, function(request, response) {
var params = {
alias: 'creditInsurance',
code: 'clientDeactivate',
bodyParams: {
clientId: request.params.clientId
}
};
mail.sendWithTemplate('notification-alias', params, error => {
if (error)
response.status(400).json({message: error.message});
return response.json();
});
});
module.exports = router;
// Single user notification // Single user notification
/* router.post('/:recipient/noticeUserSend', function(request, response) { /* router.post('/:recipient/noticeUserSend', function(request, response) {
var params = { var params = {
@ -147,33 +286,3 @@ router.get('/sepa-core/:clientId', function(request, response) {
return response.json(result); return response.json(result);
}); });
}); */ }); */
// Payment method changes
router.post('/payment-update/:clientId', function(request, response) {
mail.sendWithTemplate('payment-update', {clientId: request.params.clientId}, error => {
if (error)
return response.status(400).json({message: error.message});
return response.json();
});
});
// Send notification to alias creditInsurance on client deactivate
router.post('/client-deactivate/:clientId', function(request, response) {
var params = {
alias: 'creditInsurance',
code: 'clientDeactivate',
bodyParams: {
clientId: request.params.clientId
}
};
mail.sendWithTemplate('notification-alias', params, error => {
if (error)
response.status(400).json({message: error.message});
return response.json();
});
});
module.exports = router;

View File

@ -1,5 +1,7 @@
var express = require('express'); var express = require('express');
var router = new express.Router(); var router = new express.Router();
var fs = require('fs');
var path = require('path');
// Mailer default page // Mailer default page
router.get('/', function(request, response) { router.get('/', function(request, response) {
@ -9,4 +11,20 @@ router.get('/', function(request, response) {
// Notifications // Notifications
router.use('/notification', require('./route/notification.js')); router.use('/notification', require('./route/notification.js'));
// Serve static images
router.use('/static/:template/:image', function(request, response) {
let imagePath = path.join(__dirname, '/template/', request.params.template, '/image/', request.params.image);
fs.stat(imagePath, function(error) {
if (error)
return response.json({message: 'Image not found'});
let readStream = fs.createReadStream(imagePath);
readStream.on('open', function() {
readStream.pipe(response);
});
});
});
module.exports = router; module.exports = router;

View File

@ -15,7 +15,7 @@ module.exports = {
get: function(template, params, cb) { get: function(template, params, cb) {
var templatePath = path.join(__dirname, 'template', `${template}`, `index.html`); var templatePath = path.join(__dirname, 'template', `${template}`, `index.html`);
var classPath = path.join(__dirname, 'template', `${template}`, `${template}.js`); var classPath = path.join(__dirname, 'template', `${template}`, `${template}.js`);
var stylePath = path.join(__dirname, 'template', `${template}`, 'static', 'css', 'style.css'); var stylePath = path.join(__dirname, 'template', `${template}`, 'style.css');
fs.stat(templatePath, (error, stat) => { fs.stat(templatePath, (error, stat) => {
if (error) if (error)
@ -65,6 +65,8 @@ module.exports = {
return cb(error); return cb(error);
instance._ = result.locale; instance._ = result.locale;
instance.isPreview = params.isPreview;
getDataCb(null, result); getDataCb(null, result);
}); });
}); });
@ -173,14 +175,17 @@ module.exports = {
// Template default attachments // Template default attachments
for (var i = 0; i < tplAttachments.length; i++) { for (var i = 0; i < tplAttachments.length; i++) {
let name = tplAttachments[i].replace('src="cid:', '').replace('"', ''); let src = tplAttachments[i].replace('src="cid:', '').replace('"', '').split('/');
let attachmentTpl = src[0];
let attachment = src[1];
if (isPreview) { if (isPreview) {
let attachmentPath = `/mailer/static/images/${name}`; let attachmentPath = `/mailer/static/${attachmentTpl}/${attachment}`;
body = body.replace(tplAttachments[i], `src="${attachmentPath}"`); body = body.replace(tplAttachments[i], `src="${attachmentPath}"`);
} else { } else {
let attachmentPath = path.join(__dirname, '../static', 'images', name); let attachmentPath = path.join(__dirname, 'template', `${attachmentTpl}`, 'image', attachment);
attachments.push({filename: name, path: attachmentPath, cid: name}); let attachmentName = attachmentTpl + '/' + attachment;
attachments.push({filename: attachmentName, path: attachmentPath, cid: attachmentName});
} }
} }

View File

@ -14,10 +14,11 @@ module.exports = class ClientWelcome {
c.email recipient c.email recipient
FROM client c FROM client c
JOIN account.user u ON u.id = c.id JOIN account.user u ON u.id = c.id
LEFT JOIN worker w ON w.id = c.workerFk LEFT JOIN worker w ON w.id = c.salesPersonFk
LEFT JOIN account.user wu ON wu.id = w.userFk LEFT JOIN account.user wu ON wu.id = w.userFk
JOIN country ct ON ct.id = c.countryFk JOIN country ct ON ct.id = c.countryFk
WHERE c.id = ?`; WHERE c.id = ?`;
database.pool.query(query, [params.clientId], (error, result) => { database.pool.query(query, [params.clientId], (error, result) => {
if (error || result.length == 0) if (error || result.length == 0)
return cb(new Error('No template data found')); return cb(new Error('No template data found'));

View File

@ -22,6 +22,7 @@
<p>{{_.dear}}</p> <p>{{_.dear}}</p>
<p>{{{_.bodyDescription}}}</p> <p>{{{_.bodyDescription}}}</p>
<p> <p>
<div>{{_.clientNumber}} <strong>{{clientId}}</strong></div>
<div>{{_.user}} <strong>{{userName}}</strong></div> <div>{{_.user}} <strong>{{userName}}</strong></div>
<div>{{_.password}} <strong>********</strong> {{_.passwordResetText}}</div> <div>{{_.password}} <strong>********</strong> {{_.passwordResetText}}</div>
</p> </p>

View File

@ -3,6 +3,7 @@
"title": "¡LE DAMOS LA BIENVENIDA!", "title": "¡LE DAMOS LA BIENVENIDA!",
"dear": "Estimado cliente,", "dear": "Estimado cliente,",
"bodyDescription": "Sus datos para poder comprar en la web de verdnatura (<a href=\"https://www.verdnatura.es\" title=\"Visitar Verdnatura\" target=\"_blank\">https://www.verdnatura.es</a>) o en nuestras aplicaciones para <a href=\"https://goo.gl/3hC2mG\" title=\"App Store\" target=\"_blank\">iOS</a> y <a href=\"https://goo.gl/8obvLc\" title=\"Google Play\" target=\"_blank\">Android</a> (<a href=\"https://www.youtube.com/watch?v=gGfEtFm8qkw\" target=\"_blank\"><strong>Ver tutorial de uso</strong></a>), son:", "bodyDescription": "Sus datos para poder comprar en la web de verdnatura (<a href=\"https://www.verdnatura.es\" title=\"Visitar Verdnatura\" target=\"_blank\">https://www.verdnatura.es</a>) o en nuestras aplicaciones para <a href=\"https://goo.gl/3hC2mG\" title=\"App Store\" target=\"_blank\">iOS</a> y <a href=\"https://goo.gl/8obvLc\" title=\"Google Play\" target=\"_blank\">Android</a> (<a href=\"https://www.youtube.com/watch?v=gGfEtFm8qkw\" target=\"_blank\"><strong>Ver tutorial de uso</strong></a>), son:",
"clientNumber": "Identificador de cliente:",
"user": "Usuario:", "user": "Usuario:",
"password": "Contraseña:", "password": "Contraseña:",
"passwordResetText": "(Va a recibir un correo para establecer la contraseña)", "passwordResetText": "(Va a recibir un correo para establecer la contraseña)",

View File

@ -0,0 +1,4 @@
<svg fill="#000000" height="48" viewBox="0 0 24 24" width="48" xmlns="http://www.w3.org/2000/svg">
<path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/>
<path d="M0 0h24v24H0z" fill="none"/>
</svg>

After

Width:  |  Height:  |  Size: 205 B

View File

@ -0,0 +1,4 @@
<svg fill="#000000" height="48" viewBox="0 0 24 24" width="48" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M11.5 9C10.12 9 9 10.12 9 11.5s1.12 2.5 2.5 2.5 2.5-1.12 2.5-2.5S12.88 9 11.5 9zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-3.21 14.21l-2.91-2.91c-.69.44-1.51.7-2.39.7C9.01 16 7 13.99 7 11.5S9.01 7 11.5 7 16 9.01 16 11.5c0 .88-.26 1.69-.7 2.39l2.91 2.9-1.42 1.42z"/>
</svg>

After

Width:  |  Height:  |  Size: 461 B

View File

@ -5,7 +5,8 @@ var format = require(path.join(__dirname, '../../util/format.js'));
module.exports = class Footer { module.exports = class Footer {
getData(params, cb) { getData(params, cb) {
let query = `SELECT let query = `SELECT
socialName socialName,
LOWER(ct.code) countryCode
FROM client c FROM client c
JOIN country ct ON ct.id = c.countryFk JOIN country ct ON ct.id = c.countryFk
WHERE c.id = ?`; WHERE c.id = ?`;

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -2,10 +2,10 @@
<div class="buttons"> <div class="buttons">
<a href="https://www.verdnatura.es" target="_blank"><div class="btn"> <a href="https://www.verdnatura.es" target="_blank"><div class="btn">
<span class="text">{{_.actionButton}}</span> <span class="text">{{_.actionButton}}</span>
<span class="icon"><img src="cid:action.png"/></span> <span class="icon"><img src="cid:footer/action.png"/></span>
</div></a><a href="https://goo.gl/forms/j8WSL151ZW6QtlT72" target="_blank"><div class="btn"> </div></a><a href="https://goo.gl/forms/j8WSL151ZW6QtlT72" target="_blank"><div class="btn">
<span class="text">{{_.infoButton}}</span> <span class="text">{{_.infoButton}}</span>
<span class="icon"><img src="cid:info.png"/></span> <span class="icon"><img src="cid:footer/info.png"/></span>
</div></a> </div></a>
</div> </div>
<!-- Action button block --> <!-- Action button block -->
@ -13,22 +13,22 @@
<!-- Networks block --> <!-- Networks block -->
<div class="footer"> <div class="footer">
<a href="https://www.facebook.com/Verdnatura" target="_blank"> <a href="https://www.facebook.com/Verdnatura" target="_blank">
<img src="cid:facebook.png" alt="Facebook"/> <img src="cid:footer/facebook.png" alt="Facebook"/>
</a> </a>
<a href="https://www.twitter.com/Verdnatura" target="_blank"> <a href="https://www.twitter.com/Verdnatura" target="_blank">
<img src="cid:twitter.png" alt="Twitter"/> <img src="cid:footer/twitter.png" alt="Twitter"/>
</a> </a>
<a href="https://www.youtube.com/Verdnatura" target="_blank"> <a href="https://www.youtube.com/Verdnatura" target="_blank">
<img src="cid:youtube.png" alt="Youtube"/> <img src="cid:footer/youtube.png" alt="Youtube"/>
</a> </a>
<a href="https://www.pinterest.com/Verdnatura" target="_blank"> <a href="https://www.pinterest.com/Verdnatura" target="_blank">
<img src="cid:pinterest.png" alt="Pinterest"/> <img src="cid:footer/pinterest.png" alt="Pinterest"/>
</a> </a>
<a href="https://www.instagram.com/Verdnatura" target="_blank"> <a href="https://www.instagram.com/Verdnatura" target="_blank">
<img src="cid:instagram.png" alt="Instagram"/> <img src="cid:footer/instagram.png" alt="Instagram"/>
</a> </a>
<a href="https://www.linkedin.com/company/verdnatura" target="_blank"> <a href="https://www.linkedin.com/company/verdnatura" target="_blank">
<img src="cid:linkedin.png" alt="Linkedin"/> <img src="cid:footer/linkedin.png" alt="Linkedin"/>
</a> </a>
</div> </div>
<!-- Networks block end --> <!-- Networks block end -->

View File

@ -5,7 +5,8 @@ var format = require(path.join(__dirname, '../../util/format.js'));
module.exports = class Header { module.exports = class Header {
getData(params, cb) { getData(params, cb) {
let query = `SELECT let query = `SELECT
c.name AS clientName c.name AS clientName,
LOWER(ct.code) countryCode
FROM client c FROM client c
JOIN country ct ON ct.id = c.countryFk JOIN country ct ON ct.id = c.countryFk
WHERE c.id = ?`; WHERE c.id = ?`;

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -1,3 +1,3 @@
<div> <div>
<a href="https://www.verdnatura.es"/><img src="cid:header.png" alt="VerdNatura"/></a> <a href="https://www.verdnatura.es"/><img src="cid:header/logo.png" alt="VerdNatura"/></a>
</div> </div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -0,0 +1,87 @@
<!DOCTYPE html>
<html lang="es">
<head>
<title>{{_.subject}}</title>
<meta charset="utf8"/>
</head>
<body>
<div class="wrapper">
<div class="container">
<!-- Header block -->
{{$.header}}
<!-- Header block end -->
<!-- Title block -->
<div class="title">
<h1>{{_.title}}</h1>
</div>
<!-- Title block end -->
<!-- Mail body block -->
<div class="body">
<p>{{_.dear}}</p>
<p>{{_.bodyDescription}}</p>
<p>{{_.termLimits}}</p>
<p>
{{_.payMethod}}
<ol>
<li>{{_.payMethodOption1}}</li>
<li>{{_.payMethodOption2}}</li>
</ol>
</p>
<p>
{{_.legalActions}}
<ol type="a">
<li>{{_.legalActionsOption1}}</li>
<li>{{_.legalActionsOption2}}</li>
<li>{{_.legalActionsOption3}}</li>
</ol>
</p>
<p>{{_.contact}}</p>
<p>{{_.waitingForNews}}</p>
<p>{{_.conclusion}}</p>
<p>
<div class="row">
<div class="text">{{bankName}}</div>
<div class="control">{{iban}}</div>
<div class="description">
<div class="line"><span>{{_.accountTransferData}}</span></div>
</div>
</div>
</p>
{{#isPreview}}
<a href="/print/manuscript/letter-debtor/{{companyId}}/{{clientId}}/preview?token={{token}}" target="_blank" title="Ver adjunto">
<div class="attachment">
<div class="attachment-icon">
<img src="cid:default/preview.svg" alt="Ver adjunto"/>
</div>
<span>Ver adjunto</span>
</div>
</a>
<a href="/print/manuscript/letter-debtor/{{companyId}}/{{clientId}}?token={{token}}" target="_blank" title="Descargar adjunto">
<div class="attachment">
<div class="attachment-icon">
<img src="cid:default/download.svg" alt="Descargar adjunto"/>
</div>
<span>Descargar PDF</span>
</div>
</a>
{{/isPreview}}
</div>
<!-- Mail body block end -->
<!-- Footer block -->
{{$.footer}}
<!-- Footer block end -->
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,39 @@
var path = require('path');
var database = require(path.join(__dirname, '../../database.js'));
var format = require(path.join(__dirname, '../../util/format.js'));
module.exports = class LetterDebtorNd {
getData(params, cb) {
let query = `SELECT
sa.iban,
be.name AS bankName,
LOWER(ct.code) countryCode,
c.email recipient
FROM client c
JOIN company AS cny
JOIN supplierAccount AS sa ON sa.id = cny.supplierAccountFk
JOIN bankEntity be ON be.id = sa.bankEntityFk
JOIN country ct ON ct.id = c.countryFk
WHERE c.id = ? AND cny.id = ?`;
this.clientId = params.clientId;
this.companyId = params.companyId;
this.token = params.token;
database.pool.query(query, [params.clientId, params.companyId], (error, result) => {
if (error || result.length == 0)
return cb(new Error('No template data found'));
Object.assign(this, result[0]);
cb();
});
}
get previewAttachments() {
if (this.isPreview)
return `<a href="/print/manuscript/letter-debtor/${this.companyId}/${this.clientId}/preview?token=${this.token}" target="_blank" title="Ver extracto.pdf">` +
'<div class="attachment"><div class="attachment-icon"><img src="cid:attachment.png" alt="Descargar adjunto"/></div>' +
'<span>extracto.pdf</span></div></a>';
}
};

View File

@ -0,0 +1,18 @@
{
"subject": "Reiteración de aviso por saldo deudor",
"title": "AVISO REITERADO",
"dear": "Estimado cliente,",
"bodyDescription": "Nos dirigimos a Vd. nuevamente para informarle que sigue pendiente su deuda con nuestra empresa, tal y como puede comprobar en el extracto adjunto.",
"termLimits": "Dado que los plazos de pago acordados están ampliamente superados, no procede mayor dilación en la liquidación del importe adeudado.",
"payMethod": "Para ello dispone de las siguientes formas de pago:",
"payMethodOption1": "Pago online desde nuestra web",
"payMethodOption2": "Ingreso o transferencia al número de cuenta que detallamos al pie de esta carta, indicando el número de cliente.",
"legalActions": "En caso de no ser atendido este apremio de pago, nos veremos obligados a iniciar las acciones legales que procedan, entre las que están:",
"legalActionsOption1": "Inclusión en ficheros negativos sobre solvencia patrimonial y crédito.",
"legalActionsOption2": "Reclamación judicial",
"legalActionsOption3": "Cesión de deuda a una empresa de gestión de cobro",
"contact": "Para consultas, puede ponerse en contacto con nosotros en el 96 324 21 00.",
"waitingForNews": "En espera de sus noticias",
"conclusion": "Gracias por su atención.",
"accountTransferData": "Datos para transferencia bancaria"
}

View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="es">
<head>
<title>{{_.subject}}</title>
<meta charset="utf8"/>
</head>
<body>
<div class="wrapper">
<div class="container">
<!-- Header block -->
{{$.header}}
<!-- Header block end -->
<!-- Title block -->
<div class="title">
<h1>{{_.title}}</h1>
</div>
<!-- Title block end -->
<!-- Mail body block -->
<div class="body">
<p>{{_.dear}}</p>
<p>{{_.bodyDescription}}</p>
<p>{{_.viewExtract}}</p>
<p>{{_.validData}}</p>
<p>{{_.payMethod}}</p>
<p>{{_.conclusion}}</p>
<p>
<div class="row">
<div class="text">{{bankName}}</div>
<div class="control">{{iban}}</div>
<div class="description">
<div class="line"><span>{{_.accountTransferData}}</span></div>
</div>
</div>
</p>
{{#isPreview}}
<a href="/print/manuscript/letter-debtor/{{companyId}}/{{clientId}}/preview?token={{token}}" target="_blank" title="Ver adjunto">
<div class="attachment">
<div class="attachment-icon">
<img src="cid:default/preview.svg" alt="Ver adjunto"/>
</div>
<span>Ver adjunto</span>
</div>
</a>
<a href="/print/manuscript/letter-debtor/{{companyId}}/{{clientId}}?token={{token}}" target="_blank" title="Descargar adjunto">
<div class="attachment">
<div class="attachment-icon">
<img src="cid:default/download.svg" alt="Descargar adjunto"/>
</div>
<span>Descargar PDF</span>
</div>
</a>
{{/isPreview}}
</div>
<!-- Mail body block end -->
<!-- Footer block -->
{{$.footer}}
<!-- Footer block end -->
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,39 @@
var path = require('path');
var database = require(path.join(__dirname, '../../database.js'));
var format = require(path.join(__dirname, '../../util/format.js'));
module.exports = class LetterDebtorSt {
getData(params, cb) {
let query = `SELECT
sa.iban,
be.name AS bankName,
LOWER(ct.code) countryCode,
c.email recipient
FROM client c
JOIN company AS cny
JOIN supplierAccount AS sa ON sa.id = cny.supplierAccountFk
JOIN bankEntity be ON be.id = sa.bankEntityFk
JOIN country ct ON ct.id = c.countryFk
WHERE c.id = ? AND cny.id = ?`;
this.clientId = params.clientId;
this.companyId = params.companyId;
this.token = params.token;
database.pool.query(query, [params.clientId, params.companyId], (error, result) => {
if (error || result.length == 0)
return cb(new Error('No template data found'));
Object.assign(this, result[0]);
cb();
});
}
get previewAttachments() {
if (this.isPreview)
return `<a href="/print/manuscript/letter-debtor/${this.companyId}/${this.clientId}/preview?token=${this.token}" target="_blank" title="Ver extracto.pdf">` +
'<div class="attachment"><div class="attachment-icon"><img src="cid:attachment.png" alt="Descargar adjunto"/></div>' +
'<span>extracto.pdf</span></div></a>';
}
};

View File

@ -0,0 +1,11 @@
{
"subject": "Aviso inicial por saldo deudor",
"title": "AVISO INICIAL",
"dear": "Estimado cliente,",
"bodyDescription": "Por el presente escrito le comunicamos que, según nuestros datos contables, su cuenta tiene un saldo pendiente de liquidar.",
"viewExtract": "Le solicitamos compruebe que el extracto adjunto corresponde con los datos de que Vd. dispone. Nuestro departamento de administración le aclarará gustosamente cualquier duda que pueda tener, e igualmente le facilitará cualquier documento que solicite.",
"validData": "Si al comprobar los datos aportados resultaran correctos, le rogamos proceda a regularizar su situación.",
"payMethod": "Si no desea desplazarse personalmente hasta nuestras oficinas, puede realizar el pago mediante transferencia bancaria a la cuenta que figura al pie del comunicado, indicando su número de cliente, o bien puede realizar el pago online desde nuestra página web.",
"conclusion": "De antemano le agradecemos su amable colaboración.",
"accountTransferData": "Datos para transferencia bancaria"
}

View File

@ -5,7 +5,6 @@ var format = require(path.join(__dirname, '../../util/format.js'));
module.exports = class PaymentUpdate { module.exports = class PaymentUpdate {
getData(params, cb) { getData(params, cb) {
let query = `SELECT let query = `SELECT
c.id clientId,
pm.id payMethodFk, pm.id payMethodFk,
pm.name payMethodName, pm.name payMethodName,
c.dueDay, c.dueDay,
@ -16,6 +15,9 @@ module.exports = class PaymentUpdate {
JOIN payMethod pm ON pm.id = c.paymentMethodFk JOIN payMethod pm ON pm.id = c.paymentMethodFk
JOIN country ct ON ct.id = c.countryFk JOIN country ct ON ct.id = c.countryFk
WHERE c.id = ?`; WHERE c.id = ?`;
this.clientId = params.clientId;
database.pool.query(query, [params.clientId], (error, result) => { database.pool.query(query, [params.clientId], (error, result) => {
if (error || result.length == 0) if (error || result.length == 0)
return cb(new Error('No template data found')); return cb(new Error('No template data found'));

View File

@ -5,18 +5,20 @@ var format = require(path.join(__dirname, '../../util/format.js'));
module.exports = class PrinterSetup { module.exports = class PrinterSetup {
getData(params, cb) { getData(params, cb) {
let query = `SELECT let query = `SELECT
c.id clientId,
CONCAT(w.name, ' ', w.firstName) name, CONCAT(w.name, ' ', w.firstName) name,
w.phone AS phone, w.phone AS phone,
CONCAT(u.name, '@verdnatura.es') AS email, CONCAT(u.name, '@verdnatura.es') AS email,
LOWER(ct.code) countryCode, LOWER(ct.code) countryCode,
c.email recipient c.email recipient
FROM client c FROM client c
LEFT JOIN worker w ON w.id = c.workerFk LEFT JOIN worker w ON w.id = c.salesPersonFk
LEFT JOIN account.user u ON u.id = w.userFk LEFT JOIN account.user u ON u.id = w.userFk
JOIN country ct ON ct.id = c.countryFk JOIN country ct ON ct.id = c.countryFk
WHERE c.id = ?`; WHERE c.id = ?`;
this.clientId = params.clientId;
this.isPreview = params.isPreview;
database.pool.query(query, [params.clientId], (error, result) => { database.pool.query(query, [params.clientId], (error, result) => {
if (error || result.length == 0) if (error || result.length == 0)
return cb(new Error('No template data found')); return cb(new Error('No template data found'));

View File

@ -22,7 +22,26 @@
<p>{{_.dear}}</p> <p>{{_.dear}}</p>
<p>{{_.bodyDescription}}</p> <p>{{_.bodyDescription}}</p>
<p>{{_.conclusion}}</p> <p>{{_.conclusion}}</p>
{{{previewAttachments}}}
{{#isPreview}}
<a href="/print/manuscript/sepa-core/{{companyId}}/{{clientId}}/preview?token={{token}}" target="_blank" title="Ver adjunto">
<div class="attachment">
<div class="attachment-icon">
<img src="cid:default/preview.svg" alt="Ver adjunto"/>
</div>
<span>Ver adjunto</span>
</div>
</a>
<a href="/print/manuscript/sepa-core/{{companyId}}/{{clientId}}?token={{token}}" target="_blank" title="Descargar adjunto">
<div class="attachment">
<div class="attachment-icon">
<img src="cid:default/download.svg" alt="Descargar adjunto"/>
</div>
<span>Descargar PDF</span>
</div>
</a>
{{/isPreview}}
</div> </div>
<!-- Mail body block end --> <!-- Mail body block end -->

View File

@ -5,19 +5,19 @@ var format = require(path.join(__dirname, '../../util/format.js'));
module.exports = class SepaCore { module.exports = class SepaCore {
getData(params, cb) { getData(params, cb) {
let query = `SELECT let query = `SELECT
c.id clientId,
CONCAT(w.name, ' ', w.firstName) name, CONCAT(w.name, ' ', w.firstName) name,
w.phone AS phone, w.phone AS phone,
CONCAT(u.name, '@verdnatura.es') AS email, CONCAT(u.name, '@verdnatura.es') AS email,
LOWER(ct.code) countryCode, LOWER(ct.code) countryCode,
c.email recipient c.email recipient
FROM client c FROM client c
LEFT JOIN worker w ON w.id = c.workerFk LEFT JOIN worker w ON w.id = c.salesPersonFk
LEFT JOIN account.user u ON u.id = w.userFk LEFT JOIN account.user u ON u.id = w.userFk
JOIN country ct ON ct.id = c.countryFk JOIN country ct ON ct.id = c.countryFk
WHERE c.id = ?`; WHERE c.id = ?`;
this.isPreview = params.isPreview; this.clientId = params.clientId;
this.companyId = params.companyId;
this.token = params.token; this.token = params.token;
database.pool.query(query, [params.clientId], (error, result) => { database.pool.query(query, [params.clientId], (error, result) => {
@ -29,11 +29,4 @@ module.exports = class SepaCore {
cb(); cb();
}); });
} }
get previewAttachments() {
if (this.isPreview)
return `<a href="/print/manuscript/sepa-core/${this.clientId}/?token=${this.token}" target="_blank" title="Ver sepa-core.pdf">` +
'<div class="attachment"><div class="attachment-icon"><img src="cid:attachment.png" alt="Descargar adjunto"/></div>' +
'<span>sepa-core.pdf</span></div></a>';
}
}; };

View File

@ -13,13 +13,8 @@ app.use(bodyParser.urlencoded({extended: true}));
app.use('/static', express.static(path.join(__dirname, '../static'))); app.use('/static', express.static(path.join(__dirname, '../static')));
// Auth middleware
var requestToken = function(request, response, next) {
auth.init(request, response, next);
};
// Load routes // Load routes
app.use('/', requestToken, require('../application/router.js')); app.use('/', require('../application/router.js'));
app.start = function() { app.start = function() {
var listener = app.listen(config.app.port, function() { var listener = app.listen(config.app.port, function() {

View File

@ -1,3 +1,8 @@
body {
padding: 0;
margin: 0
}
img { img {
margin: 0 margin: 0
} }
@ -51,14 +56,13 @@ p {
.panel { .panel {
border: 1px solid #DDD; border: 1px solid #DDD;
margin-bottom: 10px; margin-bottom: 10px;
position: relative;
padding:10px padding:10px
} }
.row { .row {
margin-bottom: 15px; margin-bottom: 15px;
overflow: hidden; overflow: hidden
content: '';
clear: both
} }
.row .text { .row .text {
@ -71,14 +75,34 @@ p {
box-sizing: border-box box-sizing: border-box
} }
.row .text, .row .control {
overflow: hidden
}
.row .description { .row .description {
font-size: 8px; position: relative;
padding-top: 2px;
overflow: hidden;
font-size: 11px;
display: block;
color: #999 color: #999
} }
.row .v-align { .row .line {
padding-top: 5px; border-bottom: 1px solid #DDD;
line-height: 21px border-right: 1px solid #DDD;
border-left: 1px solid #DDD;
margin-top: 10px;
color: #999;
padding: 5px
}
.row .description span {
background-color: #FFF;
margin: -5px 0 0 50px;
display: block;
padding: 5px;
float: left
} }
.row:last-child { .row:last-child {
@ -99,6 +123,11 @@ p {
float: left float: left
} }
.row.inline .description {
position: static;
overflow: visible
}
.box { .box {
border-top: 1px solid #CCC; border-top: 1px solid #CCC;
border-right: 1px solid #CCC; border-right: 1px solid #CCC;
@ -112,21 +141,47 @@ p {
float: left float: left
} }
.box.crossed {
font-weight: 100;
font-size: 16px
}
.row .control .box:first-child { .row .control .box:first-child {
border-left: 1px solid #CCC; border-left: 1px solid #CCC;
} }
.font.small {
font-size: 10px
}
.font.verticalAlign {
height: 27px;
line-height: 27px
}
.font.centered {
height: 27px;
line-height: 27px;
text-align: center
}
.verticalText {
-moz-transform: rotate(90deg);
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
position: absolute;
text-align: center;
font-size: .65em;
width: 200px;
right: -115px;
top: 50%
}
.attachment { .attachment {
overflow: hidden; overflow: hidden;
margin-top: 10px margin-top: 10px
} }
.attachment:after {
content: ' ';
display: block;
clear: both
}
.attachment-icon { .attachment-icon {
float: left float: left
} }
@ -135,3 +190,32 @@ p {
padding: 16px 0 0 10px; padding: 16px 0 0 10px;
float: left float: left
} }
.columns {
overflow: hidden
}
.columns .size100 {
width: 100%;
float: left
}
.columns .size75 {
width: 75%;
float: left
}
.columns .size50 {
width: 50%;
float: left
}
.columns .size33 {
width: 33.33%;
float: left
}
.columns .size25 {
width: 25%;
float: left
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -4,22 +4,93 @@ var template = require('../template.js');
var config = require('../config.js'); var config = require('../config.js');
var pdf = require('html-pdf'); var pdf = require('html-pdf');
var path = require('path'); var path = require('path');
var auth = require('../auth.js');
// Auth middleware
var requestToken = function(request, response, next) {
auth.init(request, response, next);
};
// Sepa core // Sepa core
router.post('/sepa-core/:clientId', function(request, response, next) { router.get('/sepa-core/:companyId/:clientId', requestToken, function(request, response, next) {
template.get('sepa-core', {clientId: request.params.clientId}, (error, result) => { let params = {
clientId: request.params.clientId,
companyId: request.params.companyId
};
template.get('sepa-core', params, (error, result) => {
if (error) if (error)
return response.status(400).json({message: error.message}); return response.status(400).json({message: error.message});
pdf.create(result.body).toStream(function(error, stream) { pdf.create(result.body, config.pdf).toStream(function(error, stream) {
if (error) if (error)
throw Error(error); throw Error(error);
response.setHeader('Content-Disposition', 'attachment; filename="sepa-core.pdf"');
response.setHeader('Content-type', 'application/pdf');
stream.pipe(response); stream.pipe(response);
}); });
}); });
}); });
// Sepa core html preview
router.get('/sepa-core/:companyId/:clientId/preview', requestToken, function(request, response, next) {
let params = {
clientId: request.params.clientId,
companyId: request.params.companyId,
isPreview: true
};
template.get('sepa-core', params, (error, result) => {
if (error)
return response.status(400).json({message: error.message});
response.send(result.body);
});
});
// Debtor letter
router.get('/letter-debtor/:companyId/:clientId', requestToken, function(request, response, next) {
let params = {
clientId: request.params.clientId,
companyId: request.params.companyId
};
template.get('letter-debtor', params, (error, result) => {
if (error)
return response.status(400).json({message: error.message});
pdf.create(result.body, config.pdf).toStream(function(error, stream) {
if (error)
throw Error(error);
response.setHeader('Content-Disposition', 'attachment; filename="extracto.pdf"');
response.setHeader('Content-type', 'application/pdf');
stream.pipe(response);
});
});
});
// Debtor letter html preview
router.get('/letter-debtor/:companyId/:clientId/preview', requestToken, function(request, response, next) {
let params = {
clientId: request.params.clientId,
companyId: request.params.companyId,
isPreview: true
};
template.get('letter-debtor', params, (error, result) => {
if (error)
return response.status(400).json({message: error.message});
response.send(result.body);
});
});
module.exports = router;
// store pdf // store pdf
/* router.post('/sepa-core/:clientId', function(request, response, next) { /* router.post('/sepa-core/:clientId', function(request, response, next) {
template.get('sepa-core', {recipient: request.params.clientId}, (error, result) => { template.get('sepa-core', {recipient: request.params.clientId}, (error, result) => {
@ -36,31 +107,3 @@ router.post('/sepa-core/:clientId', function(request, response, next) {
}); });
}); });
*/ */
// Sepa core preview
router.get('/sepa-core/:clientId', function(request, response, next) {
template.get('sepa-core', {clientId: request.params.clientId}, (error, result) => {
if (error)
return response.status(400).json({message: error.message});
let options = config.pdf;
pdf.create(result.body, options).toStream(function(error, stream) {
if (error)
throw Error(error);
response.setHeader('Content-Disposition', 'inline; filename="sepa-core.pdf"');
response.setHeader('Content-type', 'application/pdf');
stream.pipe(response);
});
});
});
router.get('/sepa-core-view/:clientId', function(request, response, next) {
template.get('sepa-core', {clientId: request.params.clientId}, (error, result) => {
if (error)
return response.status(400).json({message: error.message});
response.send(result.body);
});
});
module.exports = router;

View File

@ -1,5 +1,7 @@
var express = require('express'); var express = require('express');
var router = new express.Router(); var router = new express.Router();
var fs = require('fs');
var path = require('path');
// Default page // Default page
router.get('/', function(request, response) { router.get('/', function(request, response) {
@ -9,4 +11,21 @@ router.get('/', function(request, response) {
// Manuscripts // Manuscripts
router.use('/manuscript', require('./route/manuscript.js')); router.use('/manuscript', require('./route/manuscript.js'));
// Serve static images
router.use('/static/:template/:image', function(request, response) {
let imagePath = path.join(__dirname, '/template/', request.params.template, '/image/', request.params.image);
fs.stat(imagePath, function(error) {
if (error)
return response.json({message: 'Image not found'});
let readStream = fs.createReadStream(imagePath);
readStream.on('open', function() {
readStream.pipe(response);
});
});
});
module.exports = router; module.exports = router;

View File

@ -4,6 +4,7 @@ var locale = require('./locale.js');
var inlineCss = require('inline-css'); var inlineCss = require('inline-css');
var path = require('path'); var path = require('path');
module.exports = { module.exports = {
/** /**
* Get template. * Get template.
@ -15,7 +16,7 @@ module.exports = {
get: function(template, params, cb) { get: function(template, params, cb) {
var templatePath = path.join(__dirname, 'template', `${template}`, `index.html`); var templatePath = path.join(__dirname, 'template', `${template}`, `index.html`);
var classPath = path.join(__dirname, 'template', `${template}`, `${template}.js`); var classPath = path.join(__dirname, 'template', `${template}`, `${template}.js`);
var stylePath = path.join(__dirname, 'template', `${template}`, 'static', 'css', 'style.css'); var stylePath = path.join(__dirname, 'template', `${template}`, 'style.css');
fs.stat(templatePath, (error, stat) => { fs.stat(templatePath, (error, stat) => {
if (error) if (error)
@ -43,7 +44,7 @@ module.exports = {
params.subject = title[1]; params.subject = title[1];
} }
this.renderImages(template, body, (error, body) => { this.renderImages(template, body, params.isPreview, (error, body) => {
if (error) if (error)
return cb(error); return cb(error);
@ -53,7 +54,7 @@ module.exports = {
}; };
let getDataCb = () => { let getDataCb = () => {
this.render(templatePath, instance, (error, result) => getRenderedStyles(error, result)); this.render(templatePath, params, instance, (error, result) => getRenderedStyles(error, result));
}; };
instance.getData(params, (error, result) => { instance.getData(params, (error, result) => {
@ -65,6 +66,7 @@ module.exports = {
return cb(error); return cb(error);
instance._ = result.locale; instance._ = result.locale;
instance.isPreview = params.isPreview;
getDataCb(null, result); getDataCb(null, result);
}); });
}); });
@ -77,7 +79,7 @@ module.exports = {
* @param {Object} data - Params * @param {Object} data - Params
* @param {Object} cb - Callback * @param {Object} cb - Callback
*/ */
render: function(path, data, cb) { render: function(path, params, data, cb) {
fs.readFile(path, 'utf8', (error, body) => { fs.readFile(path, 'utf8', (error, body) => {
// Find matching sub-templates // Find matching sub-templates
let regexp = new RegExp(/\{\{\$\.(.*?)\}\}/, 'ig'); let regexp = new RegExp(/\{\{\$\.(.*?)\}\}/, 'ig');
@ -89,7 +91,7 @@ module.exports = {
} }
let parentBody = body; let parentBody = body;
this.renderSub(parentBody, subTpl, data, regexp, (error, body) => { this.renderSub(parentBody, subTpl, params, regexp, (error, body) => {
if (error) if (error)
return cb(error); return cb(error);
@ -99,13 +101,13 @@ module.exports = {
}); });
}, },
renderSub: function(body, subTpl, data, regexp, cb) { renderSub: function(body, subTpl, params, regexp, cb) {
let index = 1; let index = 1;
subTpl.forEach(keyName => { subTpl.forEach(keyName => {
subTplName = keyName.replace(regexp, '$1'); subTplName = keyName.replace(regexp, '$1');
this.get(subTplName, data, (error, result) => { this.get(subTplName, params, (error, result) => {
if (error) if (error)
return cb(error); return cb(error);
@ -156,7 +158,7 @@ module.exports = {
* @param {String} body - template body * @param {String} body - template body
* @param {Object} cb - Callback * @param {Object} cb - Callback
*/ */
renderImages: function(template, body, cb) { renderImages: function(template, body, isPreview, cb) {
let tplImages = body.match(new RegExp('src="cid:(.*?)"', 'ig')); let tplImages = body.match(new RegExp('src="cid:(.*?)"', 'ig'));
if (!tplImages) if (!tplImages)
@ -164,11 +166,18 @@ module.exports = {
// Template default attachments // Template default attachments
for (var i = 0; i < tplImages.length; i++) { for (var i = 0; i < tplImages.length; i++) {
let name = tplImages[i].replace('src="cid:', '').replace('"', ''); let src = tplImages[i].replace('src="cid:', '').replace('"', '').split('/');
let attachmentTpl = src[0];
let attachment = src[1];
let imagePath = path.join(__dirname, 'template', `${template}`, 'static', 'image', name); if (isPreview) {
let imagePath = `/print/static/${attachmentTpl}/${attachment}`;
body = body.replace(tplImages[i], `src="${imagePath}"`);
} else {
let imagePath = path.join(__dirname, 'template', attachmentTpl, 'image', attachment);
body = body.replace(tplImages[i], `src="file:///${imagePath}"`); body = body.replace(tplImages[i], `src="file:///${imagePath}"`);
} }
}
cb(null, body); cb(null, body);
} }

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -1,48 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" x="0px" y="0px" width="226.229px" height="31.038px" viewBox="0 0 226.229 31.038" enable-background="new 0 0 226.229 31.038" xml:space="preserve" id="svg2" inkscape:version="0.48.1 r9760" sodipodi:docname="logo.svg"><metadata id="metadata61"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata><defs id="defs59"/><sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1366" inkscape:window-height="710" id="namedview57" showgrid="false" inkscape:zoom="4.0755163" inkscape:cx="138.56745" inkscape:cy="16.509992" inkscape:window-x="0" inkscape:window-y="26" inkscape:window-maximized="1" inkscape:current-layer="svg2"/>
<g id="Background">
</g>
<g id="Guides">
</g>
<g id="Foreground">
<g id="g7">
<g id="g9">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.417,30.321L0,0h8.233l4.26,15.582l0.349,1.276 c0.521,1.866,0.918,3.431,1.191,4.693c0.15-0.618,0.335-1.345,0.555-2.182c0.219-0.837,0.528-1.935,0.925-3.293L19.981,0h8.19 L17.671,30.321H10.417z" id="path11"/>
</g>
<g id="g13">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A0CE67" d="M139.809,19.787c-0.665,0.357-1.748,0.686-3.25,0.988 c-0.727,0.137-1.283,0.254-1.667,0.35c-0.95,0.247-1.661,0.563-2.134,0.947c-0.472,0.384-0.799,0.899-0.979,1.544 c-0.223,0.796-0.155,1.438,0.204,1.925c0.359,0.488,0.945,0.731,1.757,0.731c1.252,0,2.375-0.36,3.369-1.081 c0.994-0.721,1.653-1.665,1.98-2.831L139.809,19.787z M144.915,30.321h-7.458c0.017-0.356,0.048-0.726,0.094-1.11l0.159-1.192 c-1.318,1.026-2.627,1.786-3.927,2.279c-1.299,0.493-2.643,0.739-4.031,0.739c-2.158,0-3.7-0.593-4.625-1.779 c-0.925-1.187-1.106-2.788-0.542-4.804c0.519-1.851,1.431-3.356,2.737-4.515c1.307-1.159,3.021-1.972,5.142-2.438 c1.169-0.247,2.641-0.515,4.413-0.803c2.646-0.412,4.082-1.016,4.304-1.812l0.151-0.539c0.182-0.65,0.076-1.145-0.317-1.483 c-0.393-0.339-1.071-0.508-2.033-0.508c-1.045,0-1.934,0.214-2.666,0.643c-0.731,0.428-1.289,1.058-1.673,1.887h-6.748 c1.065-2.53,2.64-4.413,4.723-5.65s4.724-1.856,7.923-1.856c1.991,0,3.602,0.241,4.833,0.722s2.095,1.209,2.59,2.185 c0.339,0.701,0.483,1.536,0.432,2.504c-0.052,0.969-0.377,2.525-0.978,4.669l-2.375,8.483c-0.284,1.014-0.416,1.812-0.396,2.395 s0.188,0.962,0.503,1.141L144.915,30.321z" id="path15" style="fill:#8ed300;fill-opacity:1"/>
</g>
<g id="g17">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A0CE67" d="M185.7,30.321l6.27-22.393h7.049l-1.097,3.918 c1.213-1.537,2.502-2.659,3.867-3.366c1.365-0.707,2.951-1.074,4.758-1.101l-2.03,7.25c-0.304-0.042-0.608-0.072-0.912-0.093 c-0.303-0.02-0.592-0.03-0.867-0.03c-1.126,0-2.104,0.168-2.932,0.504c-0.829,0.336-1.561,0.854-2.197,1.555 c-0.406,0.467-0.789,1.136-1.149,2.007c-0.361,0.872-0.814,2.282-1.359,4.232l-2.104,7.516H185.7z" id="path19" style="fill:#8ed300;fill-opacity:1"/>
</g>
<g id="g21">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A0CE67" d="M217.631,19.787c-0.664,0.357-1.748,0.686-3.25,0.988 c-0.727,0.137-1.282,0.254-1.667,0.35c-0.95,0.247-1.661,0.563-2.134,0.947c-0.472,0.384-0.799,0.899-0.979,1.544 c-0.223,0.796-0.155,1.438,0.205,1.925c0.359,0.488,0.945,0.731,1.757,0.731c1.252,0,2.375-0.36,3.369-1.081 c0.994-0.721,1.654-1.665,1.98-2.831L217.631,19.787z M222.737,30.321h-7.458c0.017-0.356,0.048-0.726,0.094-1.11l0.159-1.192 c-1.318,1.026-2.627,1.786-3.927,2.279c-1.299,0.493-2.643,0.739-4.031,0.739c-2.158,0-3.7-0.593-4.625-1.779 c-0.926-1.187-1.106-2.788-0.542-4.804c0.519-1.851,1.431-3.356,2.737-4.515c1.306-1.159,3.02-1.972,5.142-2.438 c1.169-0.247,2.641-0.515,4.413-0.803c2.647-0.412,4.082-1.016,4.304-1.812l0.151-0.539c0.182-0.65,0.077-1.145-0.317-1.483 c-0.393-0.339-1.071-0.508-2.033-0.508c-1.045,0-1.934,0.214-2.666,0.643c-0.731,0.428-1.289,1.058-1.672,1.887h-6.748 c1.065-2.53,2.64-4.413,4.723-5.65s4.724-1.856,7.923-1.856c1.99,0,3.601,0.241,4.833,0.722s2.095,1.209,2.591,2.185 c0.339,0.701,0.483,1.536,0.431,2.504c-0.051,0.969-0.377,2.525-0.978,4.669l-2.375,8.483c-0.284,1.014-0.416,1.812-0.396,2.395 c0.02,0.583,0.188,0.962,0.503,1.141L222.737,30.321z" id="path23" style="fill:#8ed300;fill-opacity:1"/>
</g>
<g id="g25">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A0CE67" d="M188.386,7.928l-6.269,22.393h-7.174l0.864-3.085 c-1.227,1.246-2.476,2.163-3.746,2.751s-2.625,0.882-4.067,0.882c-2.471,0-4.154-0.634-5.048-1.901 c-0.895-1.268-0.993-3.149-0.294-5.644l4.31-15.396h7.338l-3.508,12.53c-0.516,1.842-0.641,3.109-0.375,3.803 s0.967,1.041,2.105,1.041c1.275,0,2.323-0.422,3.142-1.267c0.819-0.845,1.497-2.223,2.031-4.133l3.353-11.974H188.386z" id="path27" style="fill:#8ed300;fill-opacity:1"/>
</g>
<g id="g29">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A0CE67" d="M149.937,12.356l1.239-4.428h2.995l1.771-6.326h7.338 l-1.771,6.326h3.753l-1.24,4.428h-3.753l-2.716,9.702c-0.416,1.483-0.498,2.465-0.247,2.946c0.25,0.48,0.905,0.721,1.964,0.721 l0.549-0.011l0.39-0.031l-1.31,4.678c-0.811,0.148-1.596,0.263-2.354,0.344c-0.758,0.081-1.48,0.122-2.167,0.122 c-2.543,0-4.108-0.621-4.695-1.863c-0.587-1.242-0.313-3.887,0.82-7.936l2.428-8.672H149.937z" id="path31" style="fill:#8ed300;fill-opacity:1"/>
</g>
<g id="g33">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M73.875,18.896c-0.561,2.004-0.616,3.537-0.167,4.601 s1.375,1.595,2.774,1.595c1.399,0,2.605-0.524,3.62-1.574s1.806-2.59,2.375-4.622c0.526-1.879,0.556-3.334,0.09-4.363 c-0.466-1.029-1.393-1.543-2.778-1.543c-1.304,0-2.487,0.528-3.551,1.585S74.386,17.071,73.875,18.896z M96.513,0l-8.489,30.321 h-7.337l0.824-2.944c-1.166,1.22-2.369,2.121-3.61,2.703s-2.583,0.874-4.025,0.874c-2.802,0-4.772-1.081-5.912-3.243 c-1.139-2.162-1.218-4.993-0.238-8.493c0.988-3.528,2.668-6.404,5.042-8.627c2.374-2.224,4.927-3.336,7.661-3.336 c1.47,0,2.695,0.296,3.676,0.887c0.981,0.591,1.681,1.465,2.099,2.62L89.217,0H96.513z" id="path35"/>
<g id="g37">
<path fill-rule="evenodd" clip-rule="evenodd" d="M73.875,18.896c-0.561,2.004-0.616,3.537-0.167,4.601s1.375,1.595,2.774,1.595 c1.399,0,2.605-0.524,3.62-1.574s1.806-2.59,2.375-4.622c0.526-1.879,0.556-3.334,0.09-4.363 c-0.466-1.029-1.393-1.543-2.778-1.543c-1.304,0-2.487,0.528-3.551,1.585S74.386,17.071,73.875,18.896z M96.513,0l-8.489,30.321 h-7.337l0.824-2.944c-1.166,1.22-2.369,2.121-3.61,2.703s-2.583,0.874-4.025,0.874c-2.802,0-4.772-1.081-5.912-3.243 c-1.139-2.162-1.218-4.993-0.238-8.493c0.988-3.528,2.668-6.404,5.042-8.627c2.374-2.224,4.927-3.336,7.661-3.336 c1.47,0,2.695,0.296,3.676,0.887c0.981,0.591,1.681,1.465,2.099,2.62L89.217,0H96.513z" id="path39"/>
</g>
</g>
<g id="g41">
<path fill-rule="evenodd" clip-rule="evenodd" d="M46.488,30.321l6.269-22.393h7.049l-1.098,3.918 c1.213-1.537,2.502-2.659,3.868-3.366s6.015-1.074,7.822-1.101l-2.03,7.25c-0.304-0.042-0.608-0.072-0.911-0.093 c-0.304-0.02-0.592-0.03-0.867-0.03c-1.126,0-5.167,0.168-5.997,0.504c-0.829,0.336-1.561,0.854-2.196,1.555 c-0.406,0.467-0.789,1.136-1.149,2.007c-0.361,0.872-0.814,2.282-1.36,4.232l-2.104,7.516H46.488z" id="path43"/>
</g>
<g id="g45">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M32.673,16.742l8.351-0.021 c0.375-1.436,0.308-2.558-0.201-3.365s-1.402-1.211-2.68-1.211c-1.209,0-2.285,0.397-3.229,1.19S33.224,15.265,32.673,16.742z M38.817,23.278h7.043c-1.347,2.456-3.172,4.356-5.477,5.7c-2.305,1.345-4.885,2.017-7.74,2.017 c-3.473,0-5.923-1.054-7.351-3.161c-1.427-2.107-1.632-4.98-0.613-8.618c1.038-3.707,2.875-6.641,5.512-8.803 c2.637-2.163,5.678-3.244,9.123-3.244c3.555,0,6.04,1.099,7.456,3.298c1.417,2.198,1.582,5.234,0.498,9.109l-0.239,0.814 l-0.167,0.484H31.721c-0.441,1.575-0.438,2.777,0.01,3.606c0.448,0.829,1.332,1.244,2.65,1.244c0.975,0,1.836-0.206,2.583-0.617 S38.33,24.086,38.817,23.278z" id="path47"/>
<g id="g49">
<path fill-rule="evenodd" clip-rule="evenodd" d="M32.673,16.742l8.351-0.021c0.375-1.436,0.308-2.558-0.201-3.365 s-1.402-1.211-2.68-1.211c-1.209,0-2.285,0.397-3.229,1.19S33.224,15.265,32.673,16.742z M38.817,23.278h7.043 c-1.347,2.456-3.172,4.356-5.477,5.7c-2.305,1.345-4.885,2.017-7.74,2.017c-3.473,0-5.923-1.054-7.351-3.161 c-1.427-2.107-1.632-4.98-0.613-8.618c1.038-3.707,2.875-6.641,5.512-8.803c2.637-2.163,5.678-3.244,9.123-3.244 c3.555,0,6.04,1.099,7.456,3.298c1.417,2.198,1.582,5.234,0.498,9.109l-0.239,0.814l-0.167,0.484H31.721 c-0.441,1.575-0.438,2.777,0.01,3.606c0.448,0.829,1.332,1.244,2.65,1.244c0.975,0,1.836-0.206,2.583-0.617 S38.33,24.086,38.817,23.278z" id="path51"/>
</g>
</g>
<g id="g53">
<path fill="#A0CE67" d="M112.881,30.643l-6.404-18.639l-6.455,18.639h-7.254l9.565-30.321h8.19l4.434,15.582l0.35,1.276 c0.521,1.866,0.917,3.431,1.191,4.693l0.555-2.182c0.219-0.837,0.528-1.935,0.925-3.293l4.468-16.076h8.19l-10.501,30.321 H112.881z" id="path55" style="fill:#8ed300;fill-opacity:1"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -8,6 +8,7 @@ img {
max-width: 90%; max-width: 90%;
margin: 0 auto; margin: 0 auto;
font-size: 9px; font-size: 9px;
margin: 30px;
color: #555 color: #555
} }

View File

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -1,5 +1,5 @@
<div id="pageHeader-first"> <div id="pageHeader-first">
<img src="cid:logo.svg" alt="VerdNatura"/> <img src="cid:header/logo.svg" alt="VerdNatura"/>
<p> <p>
<div>{{_.mercantileRegistry}}</div> <div>{{_.mercantileRegistry}}</div>
<div>{{_.fiscalAddress}}</div> <div>{{_.fiscalAddress}}</div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -1,48 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" x="0px" y="0px" width="226.229px" height="31.038px" viewBox="0 0 226.229 31.038" enable-background="new 0 0 226.229 31.038" xml:space="preserve" id="svg2" inkscape:version="0.48.1 r9760" sodipodi:docname="logo.svg"><metadata id="metadata61"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata><defs id="defs59"/><sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-width="1366" inkscape:window-height="710" id="namedview57" showgrid="false" inkscape:zoom="4.0755163" inkscape:cx="138.56745" inkscape:cy="16.509992" inkscape:window-x="0" inkscape:window-y="26" inkscape:window-maximized="1" inkscape:current-layer="svg2"/>
<g id="Background">
</g>
<g id="Guides">
</g>
<g id="Foreground">
<g id="g7">
<g id="g9">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.417,30.321L0,0h8.233l4.26,15.582l0.349,1.276 c0.521,1.866,0.918,3.431,1.191,4.693c0.15-0.618,0.335-1.345,0.555-2.182c0.219-0.837,0.528-1.935,0.925-3.293L19.981,0h8.19 L17.671,30.321H10.417z" id="path11"/>
</g>
<g id="g13">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A0CE67" d="M139.809,19.787c-0.665,0.357-1.748,0.686-3.25,0.988 c-0.727,0.137-1.283,0.254-1.667,0.35c-0.95,0.247-1.661,0.563-2.134,0.947c-0.472,0.384-0.799,0.899-0.979,1.544 c-0.223,0.796-0.155,1.438,0.204,1.925c0.359,0.488,0.945,0.731,1.757,0.731c1.252,0,2.375-0.36,3.369-1.081 c0.994-0.721,1.653-1.665,1.98-2.831L139.809,19.787z M144.915,30.321h-7.458c0.017-0.356,0.048-0.726,0.094-1.11l0.159-1.192 c-1.318,1.026-2.627,1.786-3.927,2.279c-1.299,0.493-2.643,0.739-4.031,0.739c-2.158,0-3.7-0.593-4.625-1.779 c-0.925-1.187-1.106-2.788-0.542-4.804c0.519-1.851,1.431-3.356,2.737-4.515c1.307-1.159,3.021-1.972,5.142-2.438 c1.169-0.247,2.641-0.515,4.413-0.803c2.646-0.412,4.082-1.016,4.304-1.812l0.151-0.539c0.182-0.65,0.076-1.145-0.317-1.483 c-0.393-0.339-1.071-0.508-2.033-0.508c-1.045,0-1.934,0.214-2.666,0.643c-0.731,0.428-1.289,1.058-1.673,1.887h-6.748 c1.065-2.53,2.64-4.413,4.723-5.65s4.724-1.856,7.923-1.856c1.991,0,3.602,0.241,4.833,0.722s2.095,1.209,2.59,2.185 c0.339,0.701,0.483,1.536,0.432,2.504c-0.052,0.969-0.377,2.525-0.978,4.669l-2.375,8.483c-0.284,1.014-0.416,1.812-0.396,2.395 s0.188,0.962,0.503,1.141L144.915,30.321z" id="path15" style="fill:#8ed300;fill-opacity:1"/>
</g>
<g id="g17">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A0CE67" d="M185.7,30.321l6.27-22.393h7.049l-1.097,3.918 c1.213-1.537,2.502-2.659,3.867-3.366c1.365-0.707,2.951-1.074,4.758-1.101l-2.03,7.25c-0.304-0.042-0.608-0.072-0.912-0.093 c-0.303-0.02-0.592-0.03-0.867-0.03c-1.126,0-2.104,0.168-2.932,0.504c-0.829,0.336-1.561,0.854-2.197,1.555 c-0.406,0.467-0.789,1.136-1.149,2.007c-0.361,0.872-0.814,2.282-1.359,4.232l-2.104,7.516H185.7z" id="path19" style="fill:#8ed300;fill-opacity:1"/>
</g>
<g id="g21">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A0CE67" d="M217.631,19.787c-0.664,0.357-1.748,0.686-3.25,0.988 c-0.727,0.137-1.282,0.254-1.667,0.35c-0.95,0.247-1.661,0.563-2.134,0.947c-0.472,0.384-0.799,0.899-0.979,1.544 c-0.223,0.796-0.155,1.438,0.205,1.925c0.359,0.488,0.945,0.731,1.757,0.731c1.252,0,2.375-0.36,3.369-1.081 c0.994-0.721,1.654-1.665,1.98-2.831L217.631,19.787z M222.737,30.321h-7.458c0.017-0.356,0.048-0.726,0.094-1.11l0.159-1.192 c-1.318,1.026-2.627,1.786-3.927,2.279c-1.299,0.493-2.643,0.739-4.031,0.739c-2.158,0-3.7-0.593-4.625-1.779 c-0.926-1.187-1.106-2.788-0.542-4.804c0.519-1.851,1.431-3.356,2.737-4.515c1.306-1.159,3.02-1.972,5.142-2.438 c1.169-0.247,2.641-0.515,4.413-0.803c2.647-0.412,4.082-1.016,4.304-1.812l0.151-0.539c0.182-0.65,0.077-1.145-0.317-1.483 c-0.393-0.339-1.071-0.508-2.033-0.508c-1.045,0-1.934,0.214-2.666,0.643c-0.731,0.428-1.289,1.058-1.672,1.887h-6.748 c1.065-2.53,2.64-4.413,4.723-5.65s4.724-1.856,7.923-1.856c1.99,0,3.601,0.241,4.833,0.722s2.095,1.209,2.591,2.185 c0.339,0.701,0.483,1.536,0.431,2.504c-0.051,0.969-0.377,2.525-0.978,4.669l-2.375,8.483c-0.284,1.014-0.416,1.812-0.396,2.395 c0.02,0.583,0.188,0.962,0.503,1.141L222.737,30.321z" id="path23" style="fill:#8ed300;fill-opacity:1"/>
</g>
<g id="g25">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A0CE67" d="M188.386,7.928l-6.269,22.393h-7.174l0.864-3.085 c-1.227,1.246-2.476,2.163-3.746,2.751s-2.625,0.882-4.067,0.882c-2.471,0-4.154-0.634-5.048-1.901 c-0.895-1.268-0.993-3.149-0.294-5.644l4.31-15.396h7.338l-3.508,12.53c-0.516,1.842-0.641,3.109-0.375,3.803 s0.967,1.041,2.105,1.041c1.275,0,2.323-0.422,3.142-1.267c0.819-0.845,1.497-2.223,2.031-4.133l3.353-11.974H188.386z" id="path27" style="fill:#8ed300;fill-opacity:1"/>
</g>
<g id="g29">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#A0CE67" d="M149.937,12.356l1.239-4.428h2.995l1.771-6.326h7.338 l-1.771,6.326h3.753l-1.24,4.428h-3.753l-2.716,9.702c-0.416,1.483-0.498,2.465-0.247,2.946c0.25,0.48,0.905,0.721,1.964,0.721 l0.549-0.011l0.39-0.031l-1.31,4.678c-0.811,0.148-1.596,0.263-2.354,0.344c-0.758,0.081-1.48,0.122-2.167,0.122 c-2.543,0-4.108-0.621-4.695-1.863c-0.587-1.242-0.313-3.887,0.82-7.936l2.428-8.672H149.937z" id="path31" style="fill:#8ed300;fill-opacity:1"/>
</g>
<g id="g33">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M73.875,18.896c-0.561,2.004-0.616,3.537-0.167,4.601 s1.375,1.595,2.774,1.595c1.399,0,2.605-0.524,3.62-1.574s1.806-2.59,2.375-4.622c0.526-1.879,0.556-3.334,0.09-4.363 c-0.466-1.029-1.393-1.543-2.778-1.543c-1.304,0-2.487,0.528-3.551,1.585S74.386,17.071,73.875,18.896z M96.513,0l-8.489,30.321 h-7.337l0.824-2.944c-1.166,1.22-2.369,2.121-3.61,2.703s-2.583,0.874-4.025,0.874c-2.802,0-4.772-1.081-5.912-3.243 c-1.139-2.162-1.218-4.993-0.238-8.493c0.988-3.528,2.668-6.404,5.042-8.627c2.374-2.224,4.927-3.336,7.661-3.336 c1.47,0,2.695,0.296,3.676,0.887c0.981,0.591,1.681,1.465,2.099,2.62L89.217,0H96.513z" id="path35"/>
<g id="g37">
<path fill-rule="evenodd" clip-rule="evenodd" d="M73.875,18.896c-0.561,2.004-0.616,3.537-0.167,4.601s1.375,1.595,2.774,1.595 c1.399,0,2.605-0.524,3.62-1.574s1.806-2.59,2.375-4.622c0.526-1.879,0.556-3.334,0.09-4.363 c-0.466-1.029-1.393-1.543-2.778-1.543c-1.304,0-2.487,0.528-3.551,1.585S74.386,17.071,73.875,18.896z M96.513,0l-8.489,30.321 h-7.337l0.824-2.944c-1.166,1.22-2.369,2.121-3.61,2.703s-2.583,0.874-4.025,0.874c-2.802,0-4.772-1.081-5.912-3.243 c-1.139-2.162-1.218-4.993-0.238-8.493c0.988-3.528,2.668-6.404,5.042-8.627c2.374-2.224,4.927-3.336,7.661-3.336 c1.47,0,2.695,0.296,3.676,0.887c0.981,0.591,1.681,1.465,2.099,2.62L89.217,0H96.513z" id="path39"/>
</g>
</g>
<g id="g41">
<path fill-rule="evenodd" clip-rule="evenodd" d="M46.488,30.321l6.269-22.393h7.049l-1.098,3.918 c1.213-1.537,2.502-2.659,3.868-3.366s6.015-1.074,7.822-1.101l-2.03,7.25c-0.304-0.042-0.608-0.072-0.911-0.093 c-0.304-0.02-0.592-0.03-0.867-0.03c-1.126,0-5.167,0.168-5.997,0.504c-0.829,0.336-1.561,0.854-2.196,1.555 c-0.406,0.467-0.789,1.136-1.149,2.007c-0.361,0.872-0.814,2.282-1.36,4.232l-2.104,7.516H46.488z" id="path43"/>
</g>
<g id="g45">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M32.673,16.742l8.351-0.021 c0.375-1.436,0.308-2.558-0.201-3.365s-1.402-1.211-2.68-1.211c-1.209,0-2.285,0.397-3.229,1.19S33.224,15.265,32.673,16.742z M38.817,23.278h7.043c-1.347,2.456-3.172,4.356-5.477,5.7c-2.305,1.345-4.885,2.017-7.74,2.017 c-3.473,0-5.923-1.054-7.351-3.161c-1.427-2.107-1.632-4.98-0.613-8.618c1.038-3.707,2.875-6.641,5.512-8.803 c2.637-2.163,5.678-3.244,9.123-3.244c3.555,0,6.04,1.099,7.456,3.298c1.417,2.198,1.582,5.234,0.498,9.109l-0.239,0.814 l-0.167,0.484H31.721c-0.441,1.575-0.438,2.777,0.01,3.606c0.448,0.829,1.332,1.244,2.65,1.244c0.975,0,1.836-0.206,2.583-0.617 S38.33,24.086,38.817,23.278z" id="path47"/>
<g id="g49">
<path fill-rule="evenodd" clip-rule="evenodd" d="M32.673,16.742l8.351-0.021c0.375-1.436,0.308-2.558-0.201-3.365 s-1.402-1.211-2.68-1.211c-1.209,0-2.285,0.397-3.229,1.19S33.224,15.265,32.673,16.742z M38.817,23.278h7.043 c-1.347,2.456-3.172,4.356-5.477,5.7c-2.305,1.345-4.885,2.017-7.74,2.017c-3.473,0-5.923-1.054-7.351-3.161 c-1.427-2.107-1.632-4.98-0.613-8.618c1.038-3.707,2.875-6.641,5.512-8.803c2.637-2.163,5.678-3.244,9.123-3.244 c3.555,0,6.04,1.099,7.456,3.298c1.417,2.198,1.582,5.234,0.498,9.109l-0.239,0.814l-0.167,0.484H31.721 c-0.441,1.575-0.438,2.777,0.01,3.606c0.448,0.829,1.332,1.244,2.65,1.244c0.975,0,1.836-0.206,2.583-0.617 S38.33,24.086,38.817,23.278z" id="path51"/>
</g>
</g>
<g id="g53">
<path fill="#A0CE67" d="M112.881,30.643l-6.404-18.639l-6.455,18.639h-7.254l9.565-30.321h8.19l4.434,15.582l0.35,1.276 c0.521,1.866,0.917,3.431,1.191,4.693l0.555-2.182c0.219-0.837,0.528-1.935,0.925-3.293l4.468-16.076h8.19l-10.501,30.321 H112.881z" id="path55" style="fill:#8ed300;fill-opacity:1"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="es">
<head>
<title>{{_.subject}}</title>
<meta charset="utf8"/>
</head>
<body>
<!-- Header block -->
{{$.header}}
<!-- Header block end -->
<!-- Body block -->
<div class="body">
<div class="columns">
<div class="size50">
<div class="size50">
<h1 style="margin-top:0" class="font extraLarge">EXTRACTO</h1>
<div class="row inline font small">
<div class="text font gray">CLIENTE:</div>
<div class="control">{{clientId}}</div>
</div>
<div class="row inline font small">
<div class="text font gray">FACTURA:</div>
<div class="control">x</div>
</div>
<div class="row inline font small">
<div class="text font gray">FECHA:</div>
<div class="control">{{currentDate}}</div>
</div>
</div>
</div>
<div class="size50">
<div class="panel">
<p>
<strong>{{supplierName}}</strong>
</p>
<div>
{{supplierStreet}}
</div>
<div>
{{supplierPostCode}}, {{supplierCity}} ({{supplierProvince}})
</div>
<div>
{{supplierCountry}}
</div>
</div>
</div>
</div>
<div class="grid" style="margin-top:30px">
<div class="row header inline">
<div style="width: 20%">Fecha</div>
<div style="width: 50%">Concepto</div>
<div style="width: 10%">Debe</div>
<div style="width: 10%">Haber</div>
<div stlye="width: 10%">Saldo</div>
</div>
<div class="row inline">
<div style="width: 20%">Fecha</div>
<div style="width: 50%">Concepto</div>
<div style="width: 10%">Debe</div>
<div style="width: 10%">Haber</div>
<div stlye="width: 10%">Saldo</div>
</div>
</div>
<div class="pull-right">
<div class="row inline">
<div class="text">
Subtotal
</div>
</div>
</div>
</div>
<!-- Body block end -->
<!-- Footer block -->
{{$.footer}}
<!-- Footer block end -->
</body>
</html>

View File

@ -0,0 +1,54 @@
var path = require('path');
var database = require(path.join(__dirname, '../../database.js'));
var format = require(path.join(__dirname, '../../util/format.js'));
module.exports = class LetterDebtor {
getData(params, cb) {
let query = `SELECT
c.id clientId,
m.code mandateCode,
LOWER(ct.code) AS countryCode,
c.email AS recipient,
c.socialName AS clientName,
c.street AS clientStreet,
c.postcode AS clientPostCode,
c.city AS clientCity,
p.name AS clientProvince,
ct.country AS clientCountry,
s.name AS supplierName,
s.street AS supplierStreet,
sc.country AS supplierCountry,
s.postCode AS supplierPostCode,
s.city AS supplierCity,
sp.name AS supplierProvince
FROM client c
JOIN country ct ON ct.id = c.countryFk
LEFT JOIN province p ON p.id = c.provinceFk
LEFT JOIN mandate m ON m.clientFk = c.id AND m.finished IS NULL
LEFT JOIN supplier s ON s.id = m.companyFk
LEFT JOIN country sc ON sc.id = s.countryFk
LEFT JOIN province sp ON sp.id = s.provinceFk
WHERE c.id = ?`;
database.pool.query(query, [params.clientId], (error, result) => {
if (error || result.length == 0)
return cb(new Error('No template data found'));
Object.assign(this, result[0]);
cb();
});
}
// Swift BIC fields
get swiftFields() {
return new Array(11);
}
// Account number fields
get accountNumberFields() {
return new Array(23);
}
get currentDate() {
return format.date(new Date(), '/');
}
};

View File

@ -0,0 +1,31 @@
{
"title": "Orden de domiciliación de adeudo directo SEPA CORE",
"toCompleteBySupplier": "A cumplimentar por el acreedor",
"toCompleteByClient": "A cumplimentar por el deudor",
"bodyDescription": "Mediante la firma de esta orden de domiciliación, el deudor autoriza (A) al acreedor a enviar instrucciones a la entidad del deudor para adeudar su cuenta y (B) a la entidad para efectuar los adeudos en su cuenta siguiendo las instrucciones del acreedor.Como parte de sus derechos, el deudor está legitimado al reembolso por su entidad en los términos y condiciones del contrato suscrito con la misma. La solicitud de reembolso deberá efectuarse dentro de las ocho semanas que adeudo en cuenta. Puede obtener información adicional sobre sus derechos en su entidad financiera.",
"orderReference": "Referencia de la orden de domiciliación",
"supplierIdentifier": "Identificador del acreedor",
"supplierName": "Nombre del acreedor",
"supplierStreet": "Dirección",
"supplierLocation": "CP - Población - Provincia",
"supplierCountry": "País",
"clientAdvice": "Debe llevar a su Entidad Bancaria una copia del documento firmado para que lo registre y evitar la devolución.",
"clientName": "Nombre del deudor/es",
"clientStreet": "Dirección del deudor",
"clientLocation": "CP - Población - Provincia",
"clientCountry": "País del deudor",
"swift": "Swift BIC",
"accountNumber": "Número de cuenta - IBAN",
"accountHolder": "(Titular/es de la cuenta de cargo)",
"accountNumberFormat": "En España el IBAN consta de 24 posiciones comenzando siempre por ES",
"paymentType": "Tipo de pago",
"recurrent": "Recurrente",
"unique": "Único",
"signLocation": "Fecha - Localidad",
"sign": "Firma del deudor y sello",
"mandatoryFields": "TODOS LOS CAMPOS HAN DE SER CUMPLIMENTADOS OBLIGATORIAMENTE.",
"sendOrder": "UNA VEZ FIRMADA ESTA ORDEN DE DOMICILIACIÓN DEBE SER ENVIADA AL ACREEDOR PARA SU CUSTODIA Y ES RECOMENDABLE FACILITAR UNA COPIA A SU ENTIDAD BANCARIA.",
"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."
}

Some files were not shown because too many files have changed in this diff Show More