Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 4090-global_invoincing
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Vicent Llopis 2022-11-11 07:47:29 +01:00
commit 9d06f5c0f0
146 changed files with 43538 additions and 3845 deletions

12
.vscode/settings.json vendored
View File

@ -2,7 +2,13 @@
{ {
// Carácter predeterminado de final de línea. // Carácter predeterminado de final de línea.
"files.eol": "\n", "files.eol": "\n",
"editor.codeActionsOnSave": { "editor.bracketPairColorization.enabled": true,
"source.fixAll.eslint": true "editor.guides.bracketPairs": true,
} "editor.formatOnSave": true,
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"editor.codeActionsOnSave": ["source.fixAll.eslint"],
"eslint.validate": [
"javascript",
"json"
]
} }

View File

@ -1,32 +1,43 @@
FROM debian:stretch-slim FROM debian:bullseye-slim
ENV TZ Europe/Madrid ENV TZ Europe/Madrid
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
# NodeJs
RUN apt-get update \ RUN apt-get update \
&& apt-get install -y --no-install-recommends \ && apt-get install -y --no-install-recommends \
curl \ curl \
ca-certificates \ ca-certificates \
gnupg2 \ gnupg2 \
libfontconfig lftp \ && curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \
&& apt-get -y install xvfb gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 \ && apt-get install -y --no-install-recommends nodejs \
libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 \ && npm install -g npm@8.19.2
libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 \
libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 \ # Puppeteer
libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget \
&& curl -sL https://deb.nodesource.com/setup_14.x | bash - \ RUN apt-get update \
&& apt-get install -y --no-install-recommends \ && apt-get install -y --no-install-recommends \
nodejs \ libfontconfig lftp xvfb gconf-service libasound2 libatk1.0-0 libc6 \
&& apt-get purge -y --auto-remove \ libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 \
gnupg2 \ libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 \
libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 \
libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 \
libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 \
fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget \
&& rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/apt/lists/* \
&& npm -g install pm2 && npm -g install pm2
# Salix
WORKDIR /salix WORKDIR /salix
COPY print/package.json print/package-lock.json print/
RUN npm --prefix ./print install --omit=dev ./print
COPY package.json package-lock.json ./ COPY package.json package-lock.json ./
COPY loopback/package.json loopback/ COPY loopback/package.json loopback/
COPY print/package.json print/ RUN npm install --omit=dev
RUN npm install --only=prod
RUN npm --prefix ./print install --only=prod ./print
COPY loopback loopback COPY loopback loopback
COPY back back COPY back back

View File

@ -47,20 +47,22 @@ module.exports = Self => {
for (let dms of dmsToDelete) { for (let dms of dmsToDelete) {
const pathHash = DmsContainer.getHash(dms.id); const pathHash = DmsContainer.getHash(dms.id);
const dmsContainer = await DmsContainer.container(pathHash); const dmsContainer = await DmsContainer.container(pathHash);
const dstFile = path.join(dmsContainer.client.root, pathHash, dms.file);
try { try {
const dstFile = path.join(dmsContainer.client.root, pathHash, dms.file);
await fs.unlink(dstFile); await fs.unlink(dstFile);
} catch (err) { } catch (err) {
continue; if (err.code != 'ENOENT')
throw err;
} }
await dms.destroy(myOptions);
const dstFolder = path.join(dmsContainer.client.root, pathHash); const dstFolder = path.join(dmsContainer.client.root, pathHash);
try { try {
await fs.rmdir(dstFolder); await fs.rmdir(dstFolder);
} catch (err) { } catch (err) {
continue; continue;
} }
await dms.destroy(myOptions);
} }
}; };
}; };

View File

@ -1,4 +1,4 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES VALUES
('InvoiceIn', 'invoiceInPdf', 'READ', 'ALLOW', 'ROLE', 'administrative'), ('InvoiceIn', 'invoiceInPdf', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceIn', 'invoiceInEmail', 'WRITE', 'ALLOW', 'ROLE', 'administrative'), ('InvoiceIn', 'invoiceInEmail', 'WRITE', 'ALLOW', 'ROLE', 'administrative');

View File

@ -47,12 +47,8 @@ module.exports = class Docker {
if (ci) network = `--network="${networkName}"`; if (ci) network = `--network="${networkName}"`;
log('Starting container...'); log('Starting container...');
const container = await this.execP(` const container = await this.execP(
docker run \ `docker run ${network} --env RUN_CHOWN=${runChown} -d ${dockerArgs} salix-db`);
${network} \
--env RUN_CHOWN=${runChown} \
-d ${dockerArgs} salix-db
`);
this.id = container.stdout.trim(); this.id = container.stdout.trim();
try { try {

View File

@ -918,7 +918,7 @@ INSERT INTO `vn`.`expeditionStateType`(`id`, `description`, `code`)
(3, 'Perdida', 'LOST'); (3, 'Perdida', 'LOST');
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `workerFk`, `externalId`, `packagingFk`, `stateTypeFk`, `hostFk`) INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `freightItemFk`, `created`, `itemFk`, `counter`, `workerFk`, `externalId`, `packagingFk`, `stateTypeFk`, `hostFk`)
VALUES VALUES
(1, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 15, 1, 18, 'UR9000006041', 94, 1, 'pc1'), (1, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 15, 1, 18, 'UR9000006041', 94, 1, 'pc1'),
(2, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 16, 2, 18, 'UR9000006041', 94, 1, NULL), (2, 1, 1, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 16, 2, 18, 'UR9000006041', 94, 1, NULL),

View File

@ -27518,7 +27518,7 @@ CREATE TABLE `expedition` (
`id` int(11) NOT NULL AUTO_INCREMENT, `id` int(11) NOT NULL AUTO_INCREMENT,
`agencyModeFk` int(11) NOT NULL, `agencyModeFk` int(11) NOT NULL,
`ticketFk` int(10) NOT NULL, `ticketFk` int(10) NOT NULL,
`isBox` int(11) DEFAULT 1 COMMENT 'Este campo realmente en un campo itemFk, haciendo referencia al artículo que nos va a facturar el proveedor de transporte.\nSe debería llamar freightItemFk', `freightItemFk` int(11) DEFAULT 1 COMMENT 'Este campo realmente en un campo itemFk, haciendo referencia al artículo que nos va a facturar el proveedor de transporte.\nSe debería llamar freightItemFk',
`created` timestamp NULL DEFAULT current_timestamp(), `created` timestamp NULL DEFAULT current_timestamp(),
`isRefund__` bit(1) DEFAULT b'0' COMMENT 'Deprecado 01/06/2022', `isRefund__` bit(1) DEFAULT b'0' COMMENT 'Deprecado 01/06/2022',
`isPickUp__` bit(1) DEFAULT b'0' COMMENT 'Deprecado 01/06/2022', `isPickUp__` bit(1) DEFAULT b'0' COMMENT 'Deprecado 01/06/2022',
@ -27534,7 +27534,7 @@ CREATE TABLE `expedition` (
`hasNewRoute` bit(1) NOT NULL DEFAULT b'0', `hasNewRoute` bit(1) NOT NULL DEFAULT b'0',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
KEY `index1` (`agencyModeFk`), KEY `index1` (`agencyModeFk`),
KEY `index2` (`isBox`), KEY `index2` (`freightItemFk`),
KEY `index3` (`created`), KEY `index3` (`created`),
KEY `index4` (`ticketFk`), KEY `index4` (`ticketFk`),
KEY `expedition_fk3_idx` (`packagingFk`), KEY `expedition_fk3_idx` (`packagingFk`),
@ -27567,7 +27567,7 @@ BEGIN
DECLARE vShipFk INT; DECLARE vShipFk INT;
IF NEW.isBox > 0 THEN IF NEW.freightItemFk > 0 THEN
UPDATE ticket SET packages = nz(packages) + 1 WHERE id = NEW.ticketFk; UPDATE ticket SET packages = nz(packages) + 1 WHERE id = NEW.ticketFk;
@ -27638,7 +27638,7 @@ DELIMITER ;;
BEGIN BEGIN
UPDATE ticket t UPDATE ticket t
SET packages = (SELECT COUNT(counter)-1 SET packages = (SELECT COUNT(counter)-1
FROM expedition e WHERE e.ticketFk = OLD.ticketFk and e.isBox) FROM expedition e WHERE e.ticketFk = OLD.ticketFk and e.freightItemFk)
WHERE t.id = OLD.ticketFk; WHERE t.id = OLD.ticketFk;
END */;; END */;;
@ -36287,7 +36287,7 @@ CREATE TABLE `sorter` (
`created` datetime NOT NULL, `created` datetime NOT NULL,
`routeFk` int(10) unsigned NOT NULL, `routeFk` int(10) unsigned NOT NULL,
`ticketFk` int(10) NOT NULL, `ticketFk` int(10) NOT NULL,
`isBox` int(11) DEFAULT 1, `freightItemFk` int(11) DEFAULT 1,
`itemFk` int(11) DEFAULT NULL, `itemFk` int(11) DEFAULT NULL,
`width` decimal(10,2) DEFAULT 0.00, `width` decimal(10,2) DEFAULT 0.00,
`depth` decimal(10,2) DEFAULT 0.00, `depth` decimal(10,2) DEFAULT 0.00,
@ -44956,7 +44956,7 @@ BEGIN
SELECT SUM((t.zonePrice - t.zoneBonus) * ebv.ratio) INTO deliveryPrice SELECT SUM((t.zonePrice - t.zoneBonus) * ebv.ratio) INTO deliveryPrice
FROM vn.ticket t FROM vn.ticket t
LEFT JOIN expedition e ON e.ticketFk = t.id LEFT JOIN expedition e ON e.ticketFk = t.id
JOIN expeditionBoxVol ebv ON ebv.boxFk = e.isBox JOIN expeditionBoxVol ebv ON ebv.boxFk = e.freightItemFk
WHERE t.id = vTicketFk; WHERE t.id = vTicketFk;
END IF; END IF;
@ -46492,7 +46492,7 @@ BEGIN
LEFT JOIN item i ON i.id = b.itemFk LEFT JOIN item i ON i.id = b.itemFk
LEFT JOIN itemType it ON it.id = i.typeFk LEFT JOIN itemType it ON it.id = i.typeFk
LEFT JOIN itemCategory ic ON ic.id = it.categoryFk LEFT JOIN itemCategory ic ON ic.id = it.categoryFk
LEFT JOIN packaging p ON p.id = b.packageFk AND NOT p.isBox LEFT JOIN packaging p ON p.id = b.packageFk AND NOT p.freightItemFk
JOIN volumeConfig vc ON TRUE JOIN volumeConfig vc ON TRUE
WHERE b.id = vSelf; WHERE b.id = vSelf;
@ -53229,7 +53229,7 @@ BEGIN
INNER JOIN vn.ticketState ts ON ts.ticketFk = exp.ticketFk INNER JOIN vn.ticketState ts ON ts.ticketFk = exp.ticketFk
LEFT JOIN vn.address a ON t.addressFk = a.id LEFT JOIN vn.address a ON t.addressFk = a.id
LEFT JOIN vn.warehouse w ON t.warehouseFk = w.id LEFT JOIN vn.warehouse w ON t.warehouseFk = w.id
WHERE t.routeFk = vRouteFk AND exp.isBox > 0; WHERE t.routeFk = vRouteFk AND exp.freightItemFk > 0;
END ;; END ;;
DELIMITER ; DELIMITER ;
/*!50003 SET sql_mode = @saved_sql_mode */ ; /*!50003 SET sql_mode = @saved_sql_mode */ ;
@ -53760,7 +53760,7 @@ BEGIN
GROUP BY sub.ticketFk GROUP BY sub.ticketFk
) sub2 ON sub2.ticketFk = t.id ) sub2 ON sub2.ticketFk = t.id
LEFT JOIN expeditionStateType est ON est.id = e.stateTypeFk LEFT JOIN expeditionStateType est ON est.id = e.stateTypeFk
WHERE t.routeFk = vRouteFk AND e.isBox <> FALSE WHERE t.routeFk = vRouteFk AND e.freightItemFk <> FALSE
ORDER BY r.created, t.priority DESC; ORDER BY r.created, t.priority DESC;
END ;; END ;;
DELIMITER ; DELIMITER ;

View File

@ -3,7 +3,7 @@
ng-transclude="prepend" ng-transclude="prepend"
class="prepend"> class="prepend">
</div> </div>
<div class="infix"> <div class="infix" >
<div class="fix prefix"></div> <div class="fix prefix"></div>
<div class="control"> <div class="control">
<section <section
@ -13,8 +13,7 @@
</section> </section>
<input <input
type="file" type="file"
accept="{{$ctrl.accept}}" accept="{{$ctrl.accept}}">
style="display: none;">
</input> </input>
</div> </div>
<div class="fix suffix"></div> <div class="fix suffix"></div>

View File

@ -4,4 +4,13 @@
.value { .value {
cursor: pointer; cursor: pointer;
} }
.control {
& > input[type=file] {
opacity: 0;
}
& > section {
position: absolute;
bottom: 0;
}
}
} }

View File

@ -24,10 +24,11 @@
} }
}, },
"node_modules/@uirouter/angularjs": { "node_modules/@uirouter/angularjs": {
"version": "1.0.29", "version": "1.0.30",
"license": "MIT", "resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.30.tgz",
"integrity": "sha512-qkc3RFZc91S5K0gc/QVAXc9LGDPXjR04vDgG/11j8+yyZEuQojXxKxdLhKIepiPzqLmGRVqzBmBc27gtqaEeZg==",
"dependencies": { "dependencies": {
"@uirouter/core": "6.0.7" "@uirouter/core": "6.0.8"
}, },
"engines": { "engines": {
"node": ">=4.0.0" "node": ">=4.0.0"
@ -37,15 +38,18 @@
} }
}, },
"node_modules/@uirouter/core": { "node_modules/@uirouter/core": {
"version": "6.0.7", "version": "6.0.8",
"license": "MIT", "resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.8.tgz",
"integrity": "sha512-Gc/BAW47i4L54p8dqYCJJZuv2s3tqlXQ0fvl6Zp2xrblELPVfxmjnc0eurx3XwfQdaqm3T6uls6tQKkof/4QMw==",
"engines": { "engines": {
"node": ">=4.0.0" "node": ">=4.0.0"
} }
}, },
"node_modules/angular": { "node_modules/angular": {
"version": "1.8.2", "version": "1.8.3",
"license": "MIT" "resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz",
"integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw==",
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward."
}, },
"node_modules/angular-animate": { "node_modules/angular-animate": {
"version": "1.8.2", "version": "1.8.2",
@ -62,8 +66,9 @@
} }
}, },
"node_modules/angular-translate": { "node_modules/angular-translate": {
"version": "2.18.4", "version": "2.19.0",
"license": "MIT", "resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.0.tgz",
"integrity": "sha512-Z/Fip5uUT2N85dPQ0sMEe1JdF5AehcDe4tg/9mWXNDVU531emHCg53ZND9Oe0dyNiGX5rWcJKmsL1Fujus1vGQ==",
"dependencies": { "dependencies": {
"angular": "^1.8.0" "angular": "^1.8.0"
}, },
@ -72,10 +77,11 @@
} }
}, },
"node_modules/angular-translate-loader-partial": { "node_modules/angular-translate-loader-partial": {
"version": "2.18.4", "version": "2.19.0",
"license": "MIT", "resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.19.0.tgz",
"integrity": "sha512-NnMw13LMV4bPQmJK7/pZOZAnPxe0M5OtUHchADs5Gye7V7feonuEnrZ8e1CKhBlv9a7IQyWoqcBa4Lnhg8gk5w==",
"dependencies": { "dependencies": {
"angular-translate": "~2.18.4" "angular-translate": "~2.19.0"
} }
}, },
"node_modules/argparse": { "node_modules/argparse": {
@ -119,8 +125,9 @@
} }
}, },
"node_modules/moment": { "node_modules/moment": {
"version": "2.29.1", "version": "2.29.4",
"license": "MIT", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
"engines": { "engines": {
"node": "*" "node": "*"
} }
@ -164,16 +171,22 @@
}, },
"dependencies": { "dependencies": {
"@uirouter/angularjs": { "@uirouter/angularjs": {
"version": "1.0.29", "version": "1.0.30",
"resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.30.tgz",
"integrity": "sha512-qkc3RFZc91S5K0gc/QVAXc9LGDPXjR04vDgG/11j8+yyZEuQojXxKxdLhKIepiPzqLmGRVqzBmBc27gtqaEeZg==",
"requires": { "requires": {
"@uirouter/core": "6.0.7" "@uirouter/core": "6.0.8"
} }
}, },
"@uirouter/core": { "@uirouter/core": {
"version": "6.0.7" "version": "6.0.8",
"resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.8.tgz",
"integrity": "sha512-Gc/BAW47i4L54p8dqYCJJZuv2s3tqlXQ0fvl6Zp2xrblELPVfxmjnc0eurx3XwfQdaqm3T6uls6tQKkof/4QMw=="
}, },
"angular": { "angular": {
"version": "1.8.2" "version": "1.8.3",
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz",
"integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw=="
}, },
"angular-animate": { "angular-animate": {
"version": "1.8.2" "version": "1.8.2"
@ -185,15 +198,19 @@
} }
}, },
"angular-translate": { "angular-translate": {
"version": "2.18.4", "version": "2.19.0",
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.0.tgz",
"integrity": "sha512-Z/Fip5uUT2N85dPQ0sMEe1JdF5AehcDe4tg/9mWXNDVU531emHCg53ZND9Oe0dyNiGX5rWcJKmsL1Fujus1vGQ==",
"requires": { "requires": {
"angular": "^1.8.0" "angular": "^1.8.0"
} }
}, },
"angular-translate-loader-partial": { "angular-translate-loader-partial": {
"version": "2.18.4", "version": "2.19.0",
"resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.19.0.tgz",
"integrity": "sha512-NnMw13LMV4bPQmJK7/pZOZAnPxe0M5OtUHchADs5Gye7V7feonuEnrZ8e1CKhBlv9a7IQyWoqcBa4Lnhg8gk5w==",
"requires": { "requires": {
"angular-translate": "~2.18.4" "angular-translate": "~2.19.0"
} }
}, },
"argparse": { "argparse": {
@ -222,7 +239,9 @@
} }
}, },
"moment": { "moment": {
"version": "2.29.1" "version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
}, },
"oclazyload": { "oclazyload": {
"version": "0.6.3" "version": "0.6.3"

View File

@ -239,5 +239,6 @@
"This route does not exists": "Esta ruta no existe", "This route does not exists": "Esta ruta no existe",
"Claim pickup order sent": "Reclamación Orden de recogida enviada [({{claimId}})]({{{claimUrl}}}) al cliente *{{clientName}}*", "Claim pickup order sent": "Reclamación Orden de recogida enviada [({{claimId}})]({{{claimUrl}}}) al cliente *{{clientName}}*",
"You don't have grant privilege": "No tienes privilegios para dar privilegios", "You don't have grant privilege": "No tienes privilegios para dar privilegios",
"You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario" "You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario",
"Empty data source": "Origen de datos vacio"
} }

View File

@ -0,0 +1,40 @@
const {Email} = require('vn-print');
module.exports = Self => {
Self.remoteMethodCtx('balanceCompensationEmail', {
description: 'Sends the debit balances compensation email with an attached PDF',
accessType: 'WRITE',
accepts: [
{
arg: 'id',
type: 'Number',
required: true,
description: 'The receipt id',
http: { source: 'path' }
}
],
returns: {
type: ['object'],
root: true
},
http: {
path: '/:id/balance-compensation-email',
verb: 'POST'
}
});
Self.balanceCompensationEmail = async (ctx, id) => {
const models = Self.app.models;
const receipt = await models.Receipt.findById(id, {fields: ['clientFk']});
const client = await models.Client.findById(receipt.clientFk, {fields:['email']});
const email = new Email('balance-compensation', {
lang: ctx.req.getLocale(),
recipient: client.email+',administracion@verdnatura.es',
id
});
return email.send();
};
};

View File

@ -0,0 +1,50 @@
const { Report } = require('vn-print');
module.exports = Self => {
Self.remoteMethodCtx('balanceCompensationPdf', {
description: 'Returns the the debit balances compensation pdf',
accessType: 'READ',
accepts: [
{
arg: 'id',
type: 'number',
required: true,
description: 'The receipt id',
http: { source: 'path' }
}
],
returns: [
{
arg: 'body',
type: 'file',
root: true
}, {
arg: 'Content-Type',
type: 'String',
http: {target: 'header'}
}, {
arg: 'Content-Disposition',
type: 'String',
http: {target: 'header'}
}
],
http: {
path: '/:id/balance-compensation-pdf',
verb: 'GET'
}
});
Self.balanceCompensationPdf = async(ctx, id) => {
const args = Object.assign({}, ctx.args);
const params = {lang: ctx.req.getLocale()};
delete args.ctx;
for (const param in args)
params[param] = args[param];
const report = new Report('balance-compensation', params);
const stream = await report.toPdfStream();
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
};
};

View File

@ -2,6 +2,8 @@ const LoopBackContext = require('loopback-context');
module.exports = function(Self) { module.exports = function(Self) {
require('../methods/receipt/filter')(Self); require('../methods/receipt/filter')(Self);
require('../methods/receipt/balanceCompensationEmail')(Self);
require('../methods/receipt/balanceCompensationPdf')(Self);
require('../methods/receipt/receiptPdf')(Self); require('../methods/receipt/receiptPdf')(Self);
Self.validateBinded('amountPaid', isNotZero, { Self.validateBinded('amountPaid', isNotZero, {

View File

@ -121,9 +121,22 @@
</vn-icon-button> </vn-icon-button>
</a> </a>
</vn-td> </vn-td>
</vn-tr> <vn-td center shrink ng-if="!balance.isInvoice">
</vn-tbody> <vn-icon-button
</vn-table> vn-dialog="send_compensation"
icon="outgoing_mail"
title="{{'Send compensation' | translate}}">
</vn-icon-button>
</vn-td>
<vn-confirm
vn-id="send_compensation"
on-accept="$ctrl.sendEmail(balance)"
question="Notify compensation"
message="Send compensation">
</vn-confirm>
</vn-tr>
</vn-tbody>
</vn-table>
</vn-card> </vn-card>
</vn-data-viewer> </vn-data-viewer>
</div> </div>

View File

@ -2,8 +2,9 @@ import ngModule from '../../module';
import Section from 'salix/components/section'; import Section from 'salix/components/section';
class Controller extends Section { class Controller extends Section {
constructor($element, $) { constructor($element, $, vnEmail) {
super($element, $); super($element, $);
this.vnEmail = vnEmail;
this.filter = { this.filter = {
include: { include: {
relation: 'company', relation: 'company',
@ -69,7 +70,7 @@ class Controller extends Section {
const balances = this.$.model.data; const balances = this.$.model.data;
balances.forEach((balance, index) => { balances.forEach((balance, index) => {
if (index === 0) if (index === 0)
balance.balance = this.getCurrentBalance(); balance.balance = this.getCurrentBalance();
if (index > 0) { if (index > 0) {
let previousBalance = balances[index - 1]; let previousBalance = balances[index - 1];
balance.balance = previousBalance.balance - (previousBalance.debit - previousBalance.credit); balance.balance = previousBalance.balance - (previousBalance.debit - previousBalance.credit);
@ -88,11 +89,15 @@ class Controller extends Section {
const params = {description: balance.description}; const params = {description: balance.description};
const endpoint = `Receipts/${balance.id}`; const endpoint = `Receipts/${balance.id}`;
this.$http.patch(endpoint, params) this.$http.patch(endpoint, params)
.then(() => this.vnApp.showSuccess(this.$t('Data saved!'))); .then(() => this.vnApp.showSuccess(this.$t('Data saved!')));
}
sendEmail(balance) {
return this.vnEmail.send(`Receipts/${balance.id}/balance-compensation-email`);
} }
} }
Controller.$inject = ['$element', '$scope']; Controller.$inject = ['$element', '$scope', 'vnEmail'];
ngModule.vnComponent('vnClientBalanceIndex', { ngModule.vnComponent('vnClientBalanceIndex', {
template: require('./index.html'), template: require('./index.html'),

View File

@ -8,4 +8,6 @@ Havings: Haber
Balance: Balance Balance: Balance
Total by company: Total por empresa Total by company: Total por empresa
Download PDF: Descargar PDF Download PDF: Descargar PDF
Send compensation: Enviar compensación
BILL: N/FRA {{ref}} BILL: N/FRA {{ref}}
Notify compensation: ¿Desea informar de la compensación al cliente por correo?

View File

@ -91,7 +91,7 @@
url="Packagings" url="Packagings"
show-field="id" show-field="id"
value-field="id" value-field="id"
where="{isBox: true}" where="{freightItemFk: true}"
ng-model="buy.packageFk" ng-model="buy.packageFk"
on-change="$ctrl.saveBuy(buy)"> on-change="$ctrl.saveBuy(buy)">
</vn-autocomplete> </vn-autocomplete>

View File

@ -32,7 +32,7 @@ module.exports = Self => {
`SELECT `SELECT
e.id, e.id,
e.ticketFk, e.ticketFk,
e.isBox, e.freightItemFk,
e.workerFk, e.workerFk,
i1.name packageItemName, i1.name packageItemName,
e.counter, e.counter,
@ -51,7 +51,7 @@ module.exports = Self => {
FROM vn.expedition e FROM vn.expedition e
LEFT JOIN vn.expeditionStateType est ON est.id = e.stateTypeFk LEFT JOIN vn.expeditionStateType est ON est.id = e.stateTypeFk
LEFT JOIN vn.item i2 ON i2.id = e.itemFk LEFT JOIN vn.item i2 ON i2.id = e.itemFk
INNER JOIN vn.item i1 ON i1.id = e.isBox INNER JOIN vn.item i1 ON i1.id = e.freightItemFk
LEFT JOIN vn.packaging p ON p.id = e.packagingFk LEFT JOIN vn.packaging p ON p.id = e.packagingFk
LEFT JOIN vn.item i3 ON i3.id = p.itemFk LEFT JOIN vn.item i3 ON i3.id = p.itemFk
LEFT JOIN account.user u ON u.id = e.workerFk LEFT JOIN account.user u ON u.id = e.workerFk

View File

@ -0,0 +1,50 @@
const {Report} = require('vn-print');
module.exports = Self => {
Self.remoteMethodCtx('collectionLabel', {
description: 'Returns the collection label',
accessType: 'READ',
accepts: [
{
arg: 'id',
type: 'number',
required: true,
description: 'The ticket id',
http: {source: 'path'}
},
],
returns: [
{
arg: 'body',
type: 'file',
root: true
}, {
arg: 'Content-Type',
type: 'String',
http: {target: 'header'}
}, {
arg: 'Content-Disposition',
type: 'String',
http: {target: 'header'}
}
],
http: {
path: '/:id/collection-label',
verb: 'GET'
}
});
Self.collectionLabel = async(ctx, id) => {
const args = Object.assign({}, ctx.args);
const params = {lang: ctx.req.getLocale()};
delete args.ctx;
for (const param in args)
params[param] = args[param];
const report = new Report('collection-label', params);
const stream = await report.toPdfStream();
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
};
};

View File

@ -16,7 +16,7 @@
"type": "number", "type": "number",
"description": "Identifier" "description": "Identifier"
}, },
"isBox": { "freightItemFk": {
"type": "number" "type": "number"
}, },
"created": { "created": {
@ -55,7 +55,7 @@
"freightItem": { "freightItem": {
"type": "belongsTo", "type": "belongsTo",
"model": "Item", "model": "Item",
"foreignKey": "isBox" "foreignKey": "freightItemFk"
}, },
"packaging": { "packaging": {
"type": "belongsTo", "type": "belongsTo",

View File

@ -33,4 +33,5 @@ module.exports = function(Self) {
require('../methods/ticket/closeByTicket')(Self); require('../methods/ticket/closeByTicket')(Self);
require('../methods/ticket/closeByAgency')(Self); require('../methods/ticket/closeByAgency')(Self);
require('../methods/ticket/closeByRoute')(Self); require('../methods/ticket/closeByRoute')(Self);
require('../methods/ticket/collectionLabel')(Self);
}; };

40216
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,7 @@
"puppeteer": "^18.0.5", "puppeteer": "^18.0.5",
"read-chunk": "^3.2.0", "read-chunk": "^3.2.0",
"require-yaml": "0.0.1", "require-yaml": "0.0.1",
"sharp": "^0.31.0", "sharp": "^0.31.2",
"smbhash": "0.0.1", "smbhash": "0.0.1",
"strong-error-handler": "^2.3.2", "strong-error-handler": "^2.3.2",
"uuid": "^3.3.3", "uuid": "^3.3.3",
@ -80,7 +80,7 @@
"html-loader-jest": "^0.2.1", "html-loader-jest": "^0.2.1",
"html-webpack-plugin": "^4.0.0-beta.11", "html-webpack-plugin": "^4.0.0-beta.11",
"identity-obj-proxy": "^3.0.0", "identity-obj-proxy": "^3.0.0",
"jasmine": "^4.1.0", "jasmine": "^4.5.0",
"jasmine-reporters": "^2.4.0", "jasmine-reporters": "^2.4.0",
"jasmine-spec-reporter": "^7.0.0", "jasmine-spec-reporter": "^7.0.0",
"jest": "^26.0.1", "jest": "^26.0.1",

View File

@ -0,0 +1,11 @@
const Stylesheet = require(`vn-print/core/stylesheet`);
const path = require('path');
const vnPrintPath = path.resolve('print');
module.exports = new Stylesheet([
`${vnPrintPath}/common/css/spacing.css`,
`${vnPrintPath}/common/css/misc.css`,
`${vnPrintPath}/common/css/layout.css`,
`${vnPrintPath}/common/css/email.css`])
.mergeStyles();

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html v-bind:lang="$i18n.locale">
<head>
<meta name="viewport" content="width=device-width" />
<meta name="format-detection" content="telephone=no" />
</head>
<body>
<table class="grid">
<tbody>
<tr>
<td>
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<slot name="header">
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
</slot>
<slot></slot>
<slot name="footer">
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
</slot>
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,12 @@
const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header');
const emailFooter = new Component('email-footer');
module.exports = {
components: {
'email-header': emailHeader.build(),
'email-footer': emailFooter.build()
},
name: 'email-body',
};

View File

@ -3,7 +3,7 @@
<div class="buttons"> <div class="buttons">
<div class="columns"> <div class="columns">
<div class="size50"> <div class="size50">
<a href="https://www.verdnatura.es" target="_blank"> <a href="https://verdnatura.es" target="_blank">
<div class="btn"> <div class="btn">
<!-- <span class="icon vn-pa-sm"><img v-bind:src="getEmailSrc('action.png')"/></span> --> <!-- <span class="icon vn-pa-sm"><img v-bind:src="getEmailSrc('action.png')"/></span> -->
<span class="text vn-pa-sm">{{ $t('buttons.webAcccess')}}</span> <span class="text vn-pa-sm">{{ $t('buttons.webAcccess')}}</span>

View File

@ -2,7 +2,7 @@ buttons:
webAcccess: Visit our website webAcccess: Visit our website
info: Help us to improve info: Help us to improve
fiscalAddress: VERDNATURA LEVANTE SL, B97367486 C/ Fenollar, 2. 46680 ALGEMESI fiscalAddress: VERDNATURA LEVANTE SL, B97367486 C/ Fenollar, 2. 46680 ALGEMESI
· www.verdnatura.es · clientes@verdnatura.es · verdnatura.es · clientes@verdnatura.es
disclaimer: '- NOTICE - This message is private and confidential, and should be used disclaimer: '- NOTICE - This message is private and confidential, and should be used
exclusively by the person receiving it. If you have received this message by mistake, exclusively by the person receiving it. If you have received this message by mistake,
please notify the sender and delete that message and any attached documents that it may contain. please notify the sender and delete that message and any attached documents that it may contain.

View File

@ -2,7 +2,7 @@ buttons:
webAcccess: Visita nuestra Web webAcccess: Visita nuestra Web
info: Ayúdanos a mejorar info: Ayúdanos a mejorar
fiscalAddress: VERDNATURA LEVANTE SL, B97367486 C/ Fenollar, 2. 46680 ALGEMESI fiscalAddress: VERDNATURA LEVANTE SL, B97367486 C/ Fenollar, 2. 46680 ALGEMESI
· www.verdnatura.es · clientes@verdnatura.es · verdnatura.es · clientes@verdnatura.es
disclaimer: '- AVISO - Este mensaje es privado y confidencial, y debe ser utilizado disclaimer: '- AVISO - Este mensaje es privado y confidencial, y debe ser utilizado
exclusivamente por la persona destinataria del mismo. Si has recibido este mensaje exclusivamente por la persona destinataria del mismo. Si has recibido este mensaje
por error, te rogamos lo comuniques al remitente y borres dicho mensaje y cualquier por error, te rogamos lo comuniques al remitente y borres dicho mensaje y cualquier

View File

@ -2,7 +2,7 @@ buttons:
webAcccess: Visitez notre site web webAcccess: Visitez notre site web
info: Aidez-nous à améliorer info: Aidez-nous à améliorer
fiscalAddress: VERDNATURA LEVANTE SL, B97367486 C/ Fenollar, 2. 46680 ALGEMESI fiscalAddress: VERDNATURA LEVANTE SL, B97367486 C/ Fenollar, 2. 46680 ALGEMESI
· www.verdnatura.es · clientes@verdnatura.es · verdnatura.es · clientes@verdnatura.es
disclaimer: "- AVIS - Ce message est privé et confidentiel et doit être utilisé disclaimer: "- AVIS - Ce message est privé et confidentiel et doit être utilisé
exclusivement par le destinataire. Si vous avez reçu ce message par erreur, exclusivement par le destinataire. Si vous avez reçu ce message par erreur,
veuillez en informer l'expéditeur et supprimer ce message ainsi que tous les veuillez en informer l'expéditeur et supprimer ce message ainsi que tous les

View File

@ -2,7 +2,7 @@ buttons:
webAcccess: Visite o nosso site webAcccess: Visite o nosso site
info: Ajude-nos a melhorar info: Ajude-nos a melhorar
fiscalAddress: VERDNATURA LEVANTE SL, B97367486 C/ Fenollar, 2. 46680 ALGEMESI fiscalAddress: VERDNATURA LEVANTE SL, B97367486 C/ Fenollar, 2. 46680 ALGEMESI
· www.verdnatura.es · clientes@verdnatura.es · verdnatura.es · clientes@verdnatura.es
disclaimer: '- AVISO - Esta mensagem é privada e confidencial e deve ser usada exclusivamente disclaimer: '- AVISO - Esta mensagem é privada e confidencial e deve ser usada exclusivamente
pela pessoa que a recebe. Se você recebeu esta mensagem por engano, notifique o remetente e pela pessoa que a recebe. Se você recebeu esta mensagem por engano, notifique o remetente e
exclua essa mensagem e todos os documentos anexos que ela possa conter. exclua essa mensagem e todos os documentos anexos que ela possa conter.

View File

@ -1,7 +1,7 @@
<header> <header>
<div class="logo"> <div class="logo">
<a href="https://www.verdnatura.es" target="_blank"> <a href="https://verdnatura.es" target="_blank">
<img v-bind:src="getEmailSrc('logo-black.png')" alt="VerdNatura"/> <img v-bind:src="getEmailSrc('logo-black.png')" alt="VerdNatura" />
</a> </a>
</div> </div>
<div class="topbar"></div> <div class="topbar"></div>

View File

@ -0,0 +1,10 @@
const Stylesheet = require(`vn-print/core/stylesheet`);
const path = require('path');
const vnPrintPath = path.resolve('print');
module.exports = new Stylesheet([
`${vnPrintPath}/common/css/layout.css`,
`${vnPrintPath}/common/css/report.css`,
`${vnPrintPath}/common/css/misc.css`])
.mergeStyles();

View File

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html v-bind:lang="$i18n.locale">
<body>
<table class="grid">
<tbody>
<tr>
<td>
<slot name="header">
<report-header v-bind="$props"></report-header>
</slot>
<slot></slot>
<slot name="footer">
<report-footer id="pageFooter" v-bind="$props"></report-footer>
</slot>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,12 @@
const Component = require(`vn-print/core/component`);
const reportHeader = new Component('report-header');
const reportFooter = new Component('report-footer');
module.exports = {
name: 'report-body',
components: {
'report-header': reportHeader.build(),
'report-footer': reportFooter.build()
},
};

View File

@ -1,2 +1,2 @@
company: company:
contactData: www.verdnatura.es - clientes@verdnatura.es contactData: verdnatura.es - clientes@verdnatura.es

View File

@ -1,2 +1,2 @@
company: company:
contactData: www.verdnatura.es - clientes@verdnatura.es contactData: verdnatura.es - clientes@verdnatura.es

View File

@ -1,2 +1,2 @@
company: company:
contactData: www.verdnatura.es - clientes@verdnatura.es contactData: verdnatura.es - clientes@verdnatura.es

View File

@ -1,2 +1,2 @@
company: company:
contactData: · www.verdnatura.es · clientes@verdnatura.es contactData: · verdnatura.es · clientes@verdnatura.es

View File

@ -32,7 +32,7 @@ class Email extends Component {
const rendered = await this.render(); const rendered = await this.render();
const attachments = []; const attachments = [];
const getAttachments = async(componentPath, files) => { const getAttachments = async(componentPath, files) => {
for (file of files) { for (const file of files) {
const fileCopy = Object.assign({}, file); const fileCopy = Object.assign({}, file);
const fileName = fileCopy.filename; const fileName = fileCopy.filename;
@ -54,15 +54,22 @@ class Email extends Component {
} }
}; };
if (instance.components) { async function getSubcomponentAttachments(instance) {
const components = instance.components; if (instance.components) {
for (let componentName in components) { const components = instance.components;
const component = components[componentName]; for (let componentName in components) {
const componentPath = `./components/${componentName}`; const component = components[componentName];
await getAttachments(componentPath, component.attachments); const componentPath = `./components/${componentName}`;
await getAttachments(componentPath, component.attachments);
if (component.components)
await getSubcomponentAttachments(component)
}
} }
} }
await getSubcomponentAttachments(instance)
if (this.attachments) if (this.attachments)
await getAttachments(this.path, this.attachments); await getAttachments(this.path, this.attachments);

View File

@ -0,0 +1,11 @@
const Stylesheet = require(`vn-print/core/stylesheet`);
const path = require('path');
const vnPrintPath = path.resolve('print');
module.exports = new Stylesheet([
`${vnPrintPath}/common/css/spacing.css`,
`${vnPrintPath}/common/css/misc.css`,
`${vnPrintPath}/common/css/layout.css`,
`${vnPrintPath}/common/css/email.css`])
.mergeStyles();

View File

@ -0,0 +1,6 @@
[
{
"filename": "balance-compensation.pdf",
"component": "balance-compensation"
}
]

View File

@ -0,0 +1,17 @@
<email-body v-bind="$props">
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<p>{{$t('description.instructions')}} {{client.name}}</p>
<p>{{$t('description.attached')}}</p>
<p>{{$t('description.response')}}</p>
<p>{{$t('description.regards')}}</p>
</div>
</div>
<div class="grid-row" v-if="isPreview">
<div class="grid-block vn-pa-ml">
<attachment v-for="attachment in attachments" v-bind:key="attachment.filename"
v-bind:attachment="attachment" v-bind:args="$props">
</attachment>
</div>
</div>
</email-body>

View File

@ -0,0 +1,36 @@
const Component = require(`vn-print/core/component`);
const emailBody = new Component('email-body');
const attachment = new Component('attachment');
module.exports = {
name: 'balance-compensation',
async serverPrefetch() {
this.client = await this.fetchClient(this.id);
},
methods: {
fetchClient(id) {
return this.findOneFromDef('client', [id]);
},
},
components: {
'email-body': emailBody.build(),
'attachment': attachment.build()
},
data() {
return {
attachments: [
{
filename: 'balance-compensation.pdf',
type: 'pdf',
path: `Receipts/${this.id}/balance-compensation-pdf`
}
]
};
},
props: {
id: {
type: Number,
required: true
}
}
};

View File

@ -0,0 +1,6 @@
subject: Compensación VerdNatura SL
description:
instructions: Buenos días,
attached: Adjuntamos escrito para su confirmación
response: Rogamos su respuesta a la mayor brevedad
regards: Un saludo

View File

@ -0,0 +1,5 @@
SELECT
c.name
FROM client c
JOIN receipt r ON r.clientFk = c.id
WHERE r.id = ?;

View File

@ -1,76 +1,37 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('dear')}},</p>
<title>{{ $t('subject') }}</title> <p v-html="$t('description', [dated])"></p>
</head> </div>
<body> </div>
<table class="grid"> <div class="grid-row">
<tbody> <div class="grid-block vn-pa-ml">
<tr> <table class="column-oriented">
<td> <thead>
<!-- Empty block --> <tr>
<div class="grid-row"> <th>{{$t('buyer')}}</th>
<div class="grid-block empty"></div> <th class="number">{{$t('percentage')}}</th>
</div> <th class="number">{{$t('dwindle')}}</th>
<!-- Header block --> <th class="number">{{$t('total')}}</th>
<div class="grid-row"> </tr>
<div class="grid-block"> </thead>
<email-header v-bind="$props"></email-header> <tbody>
</div> <tr v-for="waste in wastes" v-bind:key="waste.buyer">
</div> <td class="font gray">{{waste.buyer}}</td>
<!-- Block --> <td class="number">{{(waste.percentage / 100) | percentage(2, 2, $i18n.locale)}}</td>
<div class="grid-row"> <td class="number">{{waste.dwindle | currency('EUR', $i18n.locale)}}</td>
<div class="grid-block vn-pa-ml"> <td class="number">{{waste.total | currency('EUR', $i18n.locale)}}</td>
<h1>{{ $t('title') }}</h1> </tr>
<p>{{$t('dear')}},</p> </tbody>
<p v-html="$t('description', [dated])"></p> </table>
</div> <p v-html="$t('wasteDetailLink')"></p>
</div> <div class="external-link vn-pa-sm vn-m-md">
<!-- Block --> <a href="https://salix.verdnatura.es/#!/item/waste/index" target="_blank">
<div class="grid-row"> https://salix.verdnatura.es/#!/item/waste/index
<div class="grid-block vn-pa-ml"> </a>
<table class="column-oriented"> </div>
<thead> </div>
<tr> </div>
<th>{{$t('buyer')}}</th> </email-body>
<th class="number">{{$t('percentage')}}</th>
<th class="number">{{$t('dwindle')}}</th>
<th class="number">{{$t('total')}}</th>
</tr>
</thead>
<tbody>
<tr v-for="waste in wastes" v-bind:key="waste.buyer">
<td class="font gray">{{waste.buyer}}</td>
<td class="number">{{(waste.percentage / 100) | percentage(2, 2, $i18n.locale)}}</td>
<td class="number">{{waste.dwindle | currency('EUR', $i18n.locale)}}</td>
<td class="number">{{waste.total | currency('EUR', $i18n.locale)}}</td>
</tr>
</tbody>
</table>
<p v-html="$t('wasteDetailLink')"></p>
<div class="external-link vn-pa-sm vn-m-md">
<a href="https://salix.verdnatura.es/#!/item/waste/index" target="_blank">
https://salix.verdnatura.es/#!/item/waste/index
</a>
</div>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,6 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'buyer-week-waste', name: 'buyer-week-waste',
@ -23,8 +22,7 @@ module.exports = {
} }
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build()
'email-footer': emailFooter.build()
}, },
props: {} props: {}
}; };

View File

@ -1,46 +1,9 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('dear')}},</p>
<title>{{ $t('subject') }}</title> <p v-html="$t('description', [minDate, maxDate])"></p>
</head> </div>
<body> </div>
<table class="grid"> </email-body>
<tbody>
<tr>
<td>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('dear')}},</p>
<p v-html="$t('description', [minDate, maxDate])"></p>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,6 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'campaign-metrics', name: 'campaign-metrics',
@ -16,8 +15,7 @@ module.exports = {
} }
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build()
}, },
props: { props: {
id: { id: {

View File

@ -1,47 +1,10 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title', [id]) }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{ $t('description.dear') }},</p>
<title>{{ $t('subject') }}</title> <p v-html="instructions"></p>
</head> <p>{{ $t('description.conclusion') }}</p>
<body> </div>
<table class="grid"> </div>
<tbody> </email-body>
<tr>
<td>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title', [id]) }}</h1>
<p>{{ $t('description.dear') }},</p>
<p v-html="instructions"></p>
<p>{{ $t('description.conclusion') }}</p>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,12 +1,10 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'claim-pickup-order', name: 'claim-pickup-order',
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build()
}, },
async serverPrefetch() { async serverPrefetch() {
this.ticket = await this.fetchTicket(this.id); this.ticket = await this.fetchTicket(this.id);

View File

@ -0,0 +1,6 @@
[
{
"filename": "client-debt-statement.pdf",
"component": "client-debt-statement"
}
]

View File

@ -1,55 +1,15 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('description.instructions')}}</p>
<title>{{ $t('subject') }}</title> </div>
</head> </div>
<body> <div class="grid-row" v-if="isPreview">
<table class="grid"> <div class="grid-block vn-pa-ml">
<tbody> <attachment v-for="attachment in attachments" v-bind:key="attachment.filename"
<tr> v-bind:attachment="attachment" v-bind:args="$props">
<td> </attachment>
<!-- Empty block --> </div>
<div class="grid-row"> </div>
<div class="grid-block empty"></div> </email-body>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('description.instructions')}}</p>
</div>
</div>
<!-- Preview block -->
<div class="grid-row" v-if="isPreview">
<div class="grid-block vn-pa-ml">
<attachment v-for="attachment in attachments"
v-bind:key="attachment.filename"
v-bind:attachment="attachment"
v-bind:args="$props">
</attachment>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,13 +1,11 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
const attachment = new Component('attachment'); const attachment = new Component('attachment');
module.exports = { module.exports = {
name: 'client-debt-statement', name: 'client-debt-statement',
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build(),
'attachment': attachment.build() 'attachment': attachment.build()
}, },
data() { data() {

View File

@ -1,92 +1,56 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('dearClient')}},</p>
<title>{{ $t('subject') }}</title> <p v-html="$t('clientData')"></p>
</head>
<body>
<table class="grid">
<tbody>
<tr>
<td>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('dearClient')}},</p>
<p v-html="$t('clientData')"></p>
<p> <p>
<div>{{$t('clientId')}}: <strong>{{client.id}}</strong></div> <div>{{$t('clientId')}}: <strong>{{client.id}}</strong></div>
<div>{{$t('user')}}: <strong>{{client.userName}}</strong></div> <div>{{$t('user')}}: <strong>{{client.userName}}</strong></div>
<div>{{$t('password')}}: <strong>********</strong> <div>{{$t('password')}}: <strong>********</strong>
(<a href="https://verdnatura.es">{{$t('passwordResetText')}}</a>) (<a href="https://verdnatura.es">{{$t('passwordResetText')}}</a>)
</div> </div>
</p> </p>
<h1>{{$t('sections.howToBuy.title')}}</h1> <h1>{{$t('sections.howToBuy.title')}}</h1>
<p>{{$t('sections.howToBuy.description')}}</p> <p>{{$t('sections.howToBuy.description')}}</p>
<ol> <ol>
<li v-for="requeriment in $t('sections.howToBuy.requeriments')"> <li v-for="requeriment in $t('sections.howToBuy.requeriments')">
<span v-html="requeriment"></span> <span v-html="requeriment"></span>
</li> </li>
</ol> </ol>
<p>{{$t('sections.howToBuy.stock')}}</p> <p>{{$t('sections.howToBuy.stock')}}</p>
<p>{{$t('sections.howToBuy.delivery')}}</p> <p>{{$t('sections.howToBuy.delivery')}}</p>
<h1>{{$t('sections.howToPay.title')}}</h1> <h1>{{$t('sections.howToPay.title')}}</h1>
<p>{{$t('sections.howToPay.description')}}</p> <p>{{$t('sections.howToPay.description')}}</p>
<ul> <ul>
<li v-for="option in $t('sections.howToPay.options')"> <li v-for="option in $t('sections.howToPay.options')">
<span v-html="option"></span> <span v-html="option"></span>
</li> </li>
</ul> </ul>
<h1>{{$t('sections.toConsider.title')}}</h1> <h1>{{$t('sections.toConsider.title')}}</h1>
<p>{{$t('sections.toConsider.description')}}</p> <p>{{$t('sections.toConsider.description')}}</p>
<h4>{{$t('sections.claimsPolicy.title')}}</h4> <h4>{{$t('sections.claimsPolicy.title')}}</h4>
<p>{{$t('sections.claimsPolicy.description')}}</p> <p>{{$t('sections.claimsPolicy.description')}}</p>
<p v-html="$t('help')"></p> <p v-html="$t('help')"></p>
<p> <p>
<section v-if="client.salesPersonName"> <section v-if="client.salesPersonName">
{{$t('salesPersonName')}}: <strong>{{client.salesPersonName}}</strong> {{$t('salesPersonName')}}: <strong>{{client.salesPersonName}}</strong>
</section> </section>
<section v-if="client.salesPersonPhone"> <section v-if="client.salesPersonPhone">
{{$t('salesPersonPhone')}}: <strong>{{client.salesPersonPhone}}</strong> {{$t('salesPersonPhone')}}: <strong>{{client.salesPersonPhone}}</strong>
</section> </section>
<section v-if="client.salesPersonEmail"> <section v-if="client.salesPersonEmail">
{{$t('salesPersonEmail')}}: {{$t('salesPersonEmail')}}:
<strong><a v-bind:href="`mailto: ${client.salesPersonEmail}`" target="_blank">{{client.salesPersonEmail}}</strong> <strong><a v-bind:href="`mailto: ${client.salesPersonEmail}`"
</section> target="_blank">{{client.salesPersonEmail}}</strong>
</p> </section>
</div> </p>
</div> </div>
<!-- Footer block --> </div>
<div class="grid-row"> </email-body>
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,6 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'client-welcome', name: 'client-welcome',
@ -13,8 +12,7 @@ module.exports = {
}, },
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build()
}, },
props: { props: {
id: { id: {

View File

@ -1,8 +1,8 @@
subject: Bienvenido a Verdnatura subject: Bienvenido a Verdnatura
title: "¡Te damos la bienvenida!" title: "¡Te damos la bienvenida!"
dearClient: Estimado cliente dearClient: Estimado cliente
clientData: 'Tus datos para poder comprar en la web de Verdnatura (<a href="https://www.verdnatura.es" clientData: 'Tus datos para poder comprar en la web de Verdnatura (<a href="https://verdnatura.es"
title="Visitar Verdnatura" target="_blank" style="color: #8dba25">https://www.verdnatura.es</a>) title="Visitar Verdnatura" target="_blank" style="color: #8dba25">https://verdnatura.es</a>)
o en nuestras aplicaciones para <a href="https://goo.gl/3hC2mG" title="App Store" o en nuestras aplicaciones para <a href="https://goo.gl/3hC2mG" title="App Store"
target="_blank" style="color: #8dba25">iOS</a> y <a href="https://goo.gl/8obvLc" target="_blank" style="color: #8dba25">iOS</a> y <a href="https://goo.gl/8obvLc"
title="Google Play" target="_blank" style="color: #8dba25">Android</a>, son' title="Google Play" target="_blank" style="color: #8dba25">Android</a>, son'

View File

@ -1,55 +1,15 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('description.instructions')}}</p>
<title>{{ $t('subject') }}</title> </div>
</head> </div>
<body> <div class="grid-row" v-if="isPreview">
<table class="grid"> <div class="grid-block vn-pa-ml">
<tbody> <attachment v-for="attachment in attachments" v-bind:key="attachment.filename"
<tr> v-bind:attachment="attachment" v-bind:args="$props">
<td> </attachment>
<!-- Empty block --> </div>
<div class="grid-row"> </div>
<div class="grid-block empty"></div> </email-body>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('description.instructions')}}</p>
</div>
</div>
<!-- Preview block -->
<div class="grid-row" v-if="isPreview">
<div class="grid-block vn-pa-ml">
<attachment v-for="attachment in attachments"
v-bind:key="attachment.filename"
v-bind:attachment="attachment"
v-bind:args="$props">
</attachment>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,13 +1,11 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
const attachment = new Component('attachment'); const attachment = new Component('attachment');
module.exports = { module.exports = {
name: 'credit-request', name: 'credit-request',
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build(),
'attachment': attachment.build() 'attachment': attachment.build()
}, },
data() { data() {

View File

@ -3,3 +3,7 @@
border-radius: 3px; border-radius: 3px;
text-align: center text-align: center
} }
a {
color: #8dba25
}

View File

@ -1,69 +1,24 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('dear')}}</p>
<title>{{ $t('subject') }}</title> <p v-html="$t('description', [id])"></p>
<style type="text/css"> </div>
a { </div>
color: #8dba25 <div class="grid-row">
} <div class="grid-block vn-px-ml">
</style> <p>{{$t('copyLink')}}</p>
</head> <div class="external-link vn-pa-sm vn-m-md">
<body> https://shop.verdnatura.es/#!form=ecomerce/ticket&ticket={{id}}
<table class="grid"> </div>
<tbody> </div>
<tr> </div>
<td> <div class="grid-row">
<!-- Empty block --> <div class="grid-block vn-pa-ml">
<div class="grid-row"> <p v-html="$t('poll')"></p>
<div class="grid-block empty"></div> <p v-html="$t('help')"></p>
</div> <p v-html="$t('conclusion')"></p>
<!-- Header block --> </div>
<div class="grid-row"> </div>
<div class="grid-block"> </email-body>
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('dear')}}</p>
<p v-html="$t('description', [id])"></p>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-px-ml">
<p>{{$t('copyLink')}}</p>
<div class="external-link vn-pa-sm vn-m-md">
https://www.verdnatura.es/#!form=ecomerce/ticket&ticket={{id}}
</div>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<p v-html="$t('poll')"></p>
<p v-html="$t('help')"></p>
<p v-html="$t('conclusion')"></p>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,12 +1,10 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'delivery-note-link', name: 'delivery-note-link',
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build()
}, },
props: { props: {
id: { id: {

View File

@ -2,7 +2,7 @@ subject: Your delivery note
title: Your delivery note title: Your delivery note
dear: Dear client dear: Dear client
description: The delivery note from the order <strong>{0}</strong> is now available. <br/> description: The delivery note from the order <strong>{0}</strong> is now available. <br/>
You can download it by clicking <a href="https://www.verdnatura.es/#!form=ecomerce/ticket&ticket={0}">this link</a>. You can download it by clicking <a href="https://shop.verdnatura.es/#!form=ecomerce/ticket&ticket={0}">this link</a>.
copyLink: 'As an alternative, you can copy the following link in your browser:' copyLink: 'As an alternative, you can copy the following link in your browser:'
poll: If you wish, you can answer our satisfaction survey to poll: If you wish, you can answer our satisfaction survey to
help us provide better service. Your opinion is very important for us! help us provide better service. Your opinion is very important for us!

View File

@ -2,7 +2,7 @@ subject: Tu albarán
title: Tu albarán title: Tu albarán
dear: Estimado cliente dear: Estimado cliente
description: Ya está disponible el albarán correspondiente al pedido <strong>{0}</strong>. <br/> description: Ya está disponible el albarán correspondiente al pedido <strong>{0}</strong>. <br/>
Puedes verlo haciendo clic <a href="https://www.verdnatura.es/#!form=ecomerce/ticket&ticket={0}">en este enlace</a>. Puedes verlo haciendo clic <a href="https://shop.verdnatura.es/#!form=ecomerce/ticket&ticket={0}">en este enlace</a>.
copyLink: 'Como alternativa, puedes copiar el siguiente enlace en tu navegador:' copyLink: 'Como alternativa, puedes copiar el siguiente enlace en tu navegador:'
poll: Si lo deseas, puedes responder a nuestra encuesta de satisfacción para poll: Si lo deseas, puedes responder a nuestra encuesta de satisfacción para
ayudarnos a prestar un mejor servicio. ¡Tu opinión es muy importante para nosotros! ayudarnos a prestar un mejor servicio. ¡Tu opinión es muy importante para nosotros!

View File

@ -2,7 +2,7 @@ subject: Votre bon de livraison
title: Votre bon de livraison title: Votre bon de livraison
dear: Cher client, dear: Cher client,
description: Le bon de livraison correspondant à la commande <strong>{0}</strong> est maintenant disponible.<br/> description: Le bon de livraison correspondant à la commande <strong>{0}</strong> est maintenant disponible.<br/>
Vous pouvez le voir en cliquant <a href="https://www.verdnatura.es/#!form=ecomerce/ticket&ticket={0}" target="_blank">sur ce lien</a>. Vous pouvez le voir en cliquant <a href="https://shop.verdnatura.es/#!form=ecomerce/ticket&ticket={0}" target="_blank">sur ce lien</a>.
copyLink: 'Vous pouvez également copier le lien suivant dans votre navigateur:' copyLink: 'Vous pouvez également copier le lien suivant dans votre navigateur:'
poll: Si vous le souhaitez, vous pouvez répondre à notre questionaire de satisfaction poll: Si vous le souhaitez, vous pouvez répondre à notre questionaire de satisfaction
pour nous aider à améliorer notre service. Votre avis est très important pour nous! pour nous aider à améliorer notre service. Votre avis est très important pour nous!

View File

@ -2,7 +2,7 @@ subject: Sua nota de entrega
title: Sua nota de entrega title: Sua nota de entrega
dear: Estimado cliente dear: Estimado cliente
description: Já está disponível sua nota de entrega correspondente a encomenda numero <strong>{0}</strong>. <br/> description: Já está disponível sua nota de entrega correspondente a encomenda numero <strong>{0}</strong>. <br/>
Para ver-lo faça um clique <a href="https://www.verdnatura.es/#!form=ecomerce/ticket&ticket={0}">neste link</a>. Para ver-lo faça um clique <a href="https://shop.verdnatura.es/#!form=ecomerce/ticket&ticket={0}">neste link</a>.
copyLink: 'Como alternativa, podes copiar o siguinte link no teu navegador:' copyLink: 'Como alternativa, podes copiar o siguinte link no teu navegador:'
poll: Si o deseja, podes responder nosso questionário de satiscação para ajudar-nos a prestar-vos um melhor serviço. Tua opinião é muito importante para nós! poll: Si o deseja, podes responder nosso questionário de satiscação para ajudar-nos a prestar-vos um melhor serviço. Tua opinião é muito importante para nós!
help: Cualquer dúvida que surja, no hesites em consultar-la, <strong>Estamos aqui para help: Cualquer dúvida que surja, no hesites em consultar-la, <strong>Estamos aqui para

View File

@ -1,49 +1,12 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('dear')}},</p>
<title>{{ $t('subject') }}</title> <p v-html="$t('description', [id])"></p>
</head> <p v-html="$t('poll')"></p>
<body> <p v-html="$t('help')"></p>
<table class="grid"> <p v-html="$t('conclusion')"></p>
<tbody> </div>
<tr> </div>
<td> </email-body>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('dear')}},</p>
<p v-html="$t('description', [id])"></p>
<p v-html="$t('poll')"></p>
<p v-html="$t('help')"></p>
<p v-html="$t('conclusion')"></p>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,12 +1,10 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'delivery-note', name: 'delivery-note',
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build()
}, },
props: { props: {
id: { id: {

View File

@ -1,45 +1,8 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('description.instructions')}}</p>
<title>{{ $t('subject') }}</title> </div>
</head> </div>
<body> </email-body>
<table class="grid">
<tbody>
<tr>
<td>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('description.instructions')}}</p>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,12 +1,10 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'driver-route', name: 'driver-route',
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build()
}, },
props: { props: {
id: { id: {

View File

@ -1,57 +1,17 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('description.dear')}},</p>
<title>{{ $t('subject') }}</title> <p>{{$t('description.instructions')}}</p>
</head> <p>{{$t('description.conclusion')}}</p>
<body> </div>
<table class="grid"> </div>
<tbody> <div class="grid-row" v-if="isPreview">
<tr> <div class="grid-block vn-pa-ml">
<td> <attachment v-for="attachment in attachments" v-bind:key="attachment.filename"
<!-- Empty block --> v-bind:attachment="attachment" v-bind:args="$props">
<div class="grid-row"> </attachment>
<div class="grid-block empty"></div> </div>
</div> </div>
<!-- Header block --> </email-body>
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('description.dear')}},</p>
<p>{{$t('description.instructions')}}</p>
<p>{{$t('description.conclusion')}}</p>
</div>
</div>
<!-- Attachments block -->
<div class="grid-row" v-if="isPreview">
<div class="grid-block vn-pa-ml">
<attachment v-for="attachment in attachments"
v-bind:key="attachment.filename"
v-bind:attachment="attachment"
v-bind:args="$props">
</attachment>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,6 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
const attachment = new Component('attachment'); const attachment = new Component('attachment');
module.exports = { module.exports = {
@ -17,8 +16,7 @@ module.exports = {
}; };
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build(),
'attachment': attachment.build() 'attachment': attachment.build()
}, },
props: { props: {

View File

@ -1,49 +1,12 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('dear')}},</p>
<title>{{ $t('subject') }}</title> <p v-html="$t('description', [invoice.ref, invoice.ticketFk])"></p>
</head> <p v-html="$t('poll')"></p>
<body> <p v-html="$t('help')"></p>
<table class="grid"> <p v-html="$t('conclusion')"></p>
<tbody> </div>
<tr> </div>
<td> </email-body>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('dear')}},</p>
<p v-html="$t('description', [invoice.ref, invoice.ticketFk])"></p>
<p v-html="$t('poll')"></p>
<p v-html="$t('help')"></p>
<p v-html="$t('conclusion')"></p>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,7 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'invoice', name: 'invoice',
async serverPrefetch() { async serverPrefetch() {
@ -13,8 +11,7 @@ module.exports = {
}, },
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build()
}, },
props: { props: {
reference: { reference: {

View File

@ -1,47 +1,10 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('dear')}},</p>
<title>{{ $t('subject') }}</title> <p v-html="$t('description')"></p>
</head> <p v-html="$t('conclusion')"></p>
<body> </div>
<table class="grid"> </div>
<tbody> </email-body>
<tr>
<td>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('dear')}},</p>
<p v-html="$t('description')"></p>
<p v-html="$t('conclusion')"></p>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,11 +1,8 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'invoiceIn', name: 'invoiceIn',
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build()
} }
}; };

View File

@ -1,88 +1,48 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{ $t('sections.introduction.title') }},</p>
<title>{{ $t('subject') }}</title> <p>{{ $t('sections.introduction.description') }}</p>
</head> <p>{{ $t('sections.introduction.terms') }}</p>
<body>
<table class="grid">
<tbody>
<tr>
<td>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{ $t('sections.introduction.title') }},</p>
<p>{{ $t('sections.introduction.description') }}</p>
<p>{{ $t('sections.introduction.terms') }}</p>
<p> <p>
{{ $t('sections.payMethod.description') }}: {{ $t('sections.payMethod.description') }}:
<ol> <ol>
<li v-for="option in $t('sections.payMethod.options')"> <li v-for="option in $t('sections.payMethod.options')">
{{ option }} {{ option }}
</li> </li>
</ol> </ol>
</p> </p>
<p> <p>
{{ $t('sections.legalAction.description') }}: {{ $t('sections.legalAction.description') }}:
<ol type="a"> <ol type="a">
<li v-for="option in $t('sections.legalAction.options')"> <li v-for="option in $t('sections.legalAction.options')">
{{ option }} {{ option }}
</li> </li>
</ol> </ol>
</p> </p>
<p v-html="$t('contactPhone')"></p> <p v-html="$t('contactPhone')"></p>
<p v-html="$t('conclusion')"></p> <p v-html="$t('conclusion')"></p>
<p> <p>
<div class="row"> <div class="row">
<div class="text">{{debtor.bankName}}</div> <div class="text">{{debtor.bankName}}</div>
<div class="control">{{debtor.iban}}</div> <div class="control">{{debtor.iban}}</div>
<div class="description"> <div class="description">
<div class="line"><span>{{$t('transferAccount') }}</span></div> <div class="line"><span>{{$t('transferAccount') }}</span></div>
</div> </div>
</div> </div>
</p> </p>
</div> </div>
</div> </div>
<!-- Block --> <div class="grid-row" v-if="isPreview">
<div class="grid-row" v-if="isPreview"> <div class="grid-block vn-pa-ml">
<div class="grid-block vn-pa-ml"> <attachment v-for="attachment in attachments" v-bind:key="attachment.filename"
<attachment v-for="attachment in attachments" v-bind:attachment="attachment" v-bind:args="$props">
v-bind:key="attachment.filename" </attachment>
v-bind:attachment="attachment" </div>
v-bind:args="$props"> </div>
</attachment> </email-body>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,6 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
const attachment = new Component('attachment'); const attachment = new Component('attachment');
module.exports = { module.exports = {
@ -28,8 +27,7 @@ module.exports = {
} }
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build(),
'attachment': attachment.build() 'attachment': attachment.build()
}, },
props: { props: {

View File

@ -1,71 +1,31 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{ $t('sections.introduction.title') }},</p>
<title>{{ $t('subject') }}</title> <p>{{ $t('sections.introduction.description') }}</p>
</head>
<body>
<table class="grid">
<tbody>
<tr>
<td>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{ $t('sections.introduction.title') }},</p>
<p>{{ $t('sections.introduction.description') }}</p>
<p>{{ $t('checkExtract') }}</p> <p>{{ $t('checkExtract') }}</p>
<p>{{ $t('checkValidData') }}</p> <p>{{ $t('checkValidData') }}</p>
<p>{{ $t('payMethod') }}</p> <p>{{ $t('payMethod') }}</p>
<p>{{ $t('conclusion') }}</p> <p>{{ $t('conclusion') }}</p>
<p> <p>
<div class="row"> <div class="row">
<div class="text">{{debtor.bankName}}</div> <div class="text">{{debtor.bankName}}</div>
<div class="control">{{debtor.iban}}</div> <div class="control">{{debtor.iban}}</div>
<div class="description"> <div class="description">
<div class="line"><span>{{$t('transferAccount') }}</span></div> <div class="line"><span>{{$t('transferAccount') }}</span></div>
</div> </div>
</div> </div>
</p> </p>
</div> </div>
</div> </div>
<!-- Block --> <div class="grid-row" v-if="isPreview">
<div class="grid-row" v-if="isPreview"> <div class="grid-block vn-pa-ml">
<div class="grid-block vn-pa-ml"> <attachment v-for="attachment in attachments" v-bind:key="attachment.filename"
<attachment v-for="attachment in attachments" v-bind:attachment="attachment" v-bind:args="$props">
v-bind:key="attachment.filename" </attachment>
v-bind:attachment="attachment" </div>
v-bind:args="$props"> </div>
</attachment> </email-body>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,6 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
const attachment = new Component('attachment'); const attachment = new Component('attachment');
module.exports = { module.exports = {
@ -28,8 +27,7 @@ module.exports = {
} }
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build(),
'attachment': attachment.build() 'attachment': attachment.build()
}, },
props: { props: {

View File

@ -1,99 +1,59 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('dear')}},</p>
<title>{{ $t('subject') }}</title> <p v-html="$t('description', [started, ended])"></p>
</head> <p v-html="$t('totalResolved', [resolvedTickets])"></p>
<body> <p v-html="$t('grafanaLink')"></p>
<table class="grid"> <div class="external-link vn-pa-sm vn-m-md">
<tbody> <a
<tr> v-bind:href="'https://grafana.verdnatura.es/d/2kaHDi9Mk/osticket?orgId=1&from=' + startedTime + '&to=' + endedTime"
<td> target="_blank"
<!-- Empty block --> >
<div class="grid-row"> https://grafana.verdnatura.es/d/2kaHDi9Mk/osticket?orgId=1&from={{startedTime}}&to={{endedTime}}
<div class="grid-block empty"></div> </a>
</div> </div>
<!-- Header block --> <p v-html="$t('redmineLink')"></p>
<div class="grid-row"> <div class="external-link vn-pa-sm vn-m-md">
<div class="grid-block"> <a href="https://redmine.verdnatura.es/projects/desarrollo/issues?query_id=112" target="_blank">
<email-header v-bind="$props"></email-header> https://redmine.verdnatura.es/projects/desarrollo/issues?query_id=112
</div> </a>
</div> </div>
<!-- Block --> </div>
<div class="grid-row"> </div>
<div class="grid-block vn-pa-ml"> <div class="grid-row">
<h1>{{ $t('title') }}</h1> <div class="grid-block vn-pa-ml" v-for="technician in technicians">
<p>{{$t('dear')}},</p> <div class="table-title clearfix">
<p v-html="$t('description', [started, ended])"></p> <h2>{{technician.name}} (<strong>{{technician.tickets.length}}</strong>)</h2>
<p v-html="$t('totalResolved', [resolvedTickets])"></p> </div>
<p v-html="$t('grafanaLink')"></p> <table class="column-oriented">
<div class="external-link vn-pa-sm vn-m-md"> <thead>
<a v-bind:href="'https://grafana.verdnatura.es/d/2kaHDi9Mk/osticket?orgId=1&from=' + startedTime + '&to=' + endedTime" target="_blank"> <tr>
https://grafana.verdnatura.es/d/2kaHDi9Mk/osticket?orgId=1&from={{startedTime}}&to={{endedTime}} <th width="5%">{{$t('author')}}</th>
</a> <th width="15%">{{$t('dated')}}</th>
</div> <th width="25%">{{$t('ticketSubject')}}</th>
<p v-html="$t('redmineLink')"></p> <th width="30%">{{$t('ticketDescription')}}</th>
<div class="external-link vn-pa-sm vn-m-md"> <th width="20%">{{$t('resolution')}}</th>
<a href="https://redmine.verdnatura.es/projects/desarrollo/issues?query_id=112" target="_blank"> </tr>
https://redmine.verdnatura.es/projects/desarrollo/issues?query_id=112 </thead>
</a> <tbody v-for="ticket in technician.tickets">
</div> <tr>
</div> <td>{{ticket.author}}</td>
</div> <td class="font light-gray">
<!-- Block --> <div v-bind:title="$t('opened')">&#128275; {{ticket.created | date('%d-%m-%Y %H:%M')}}</div>
<div class="grid-row"> <div v-bind:title="$t('closed')">&#128274; {{ticket.closed | date('%d-%m-%Y %H:%M')}}</div>
<div class="grid-block vn-pa-ml" v-for="technician in technicians"> </td>
<div class="table-title clearfix"> <td>
<h2>{{technician.name}} (<strong>{{technician.tickets.length}}</strong>)</h2> <a v-bind:href="'https://cau.verdnatura.es/scp/tickets.php?id=' + ticket.ticket_id">
</div> {{ticket.number}} - {{ticket.subject}}
<table class="column-oriented"> </a>
<thead> </td>
<tr> <td class="message" v-html="ticket.description"></td>
<th width="5%">{{$t('author')}}</th> <td class="message" v-html="ticket.resolution"></td>
<th width="15%">{{$t('dated')}}</th> </tr>
<th width="25%">{{$t('ticketSubject')}}</th> </tbody>
<th width="30%">{{$t('ticketDescription')}}</th> </table>
<th width="20%">{{$t('resolution')}}</th> </div>
</tr> </div>
</thead> </email-body>
<tbody v-for="ticket in technician.tickets">
<tr>
<td>{{ticket.author}}</td>
<td class="font light-gray">
<div v-bind:title="$t('opened')">
&#128275; {{ticket.created | date('%d-%m-%Y %H:%M')}}
</div>
<div v-bind:title="$t('closed')">
&#128274; {{ticket.closed | date('%d-%m-%Y %H:%M')}}
</div>
</td>
<td>
<a v-bind:href="'https://cau.verdnatura.es/scp/tickets.php?id=' + ticket.ticket_id">
{{ticket.number}} - {{ticket.subject}}
</a>
</td>
<td class="message" v-html="ticket.description"></td>
<td class="message" v-html="ticket.resolution"></td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,6 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'osticket-report', name: 'osticket-report',
@ -61,8 +60,7 @@ module.exports = {
} }
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build()
}, },
props: {} props: {}
}; };

View File

@ -1,66 +1,28 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{ $t('sections.introduction.title') }},</p>
<title>{{ $t('subject') }}</title> <p v-html="`${$t('sections.introduction.description')}:`"></p>
</head>
<body>
<table class="grid">
<tbody>
<tr>
<td>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{ $t('sections.introduction.title') }},</p>
<p v-html="`${$t('sections.introduction.description')}:`"></p>
<p> <p>
<section> <section>
<span>{{ $t('sections.pay.method') }}:</span> <span>{{ $t('sections.pay.method') }}:</span>
<strong>{{payMethod.name}}</strong> <strong>{{payMethod.name}}</strong>
</section> </section>
<section v-if="payMethod.code != 'card'"> <section v-if="payMethod.code != 'card'">
<span>{{ $t('sections.pay.day') }}:</span> <span>{{ $t('sections.pay.day') }}:</span>
<strong>{{ $t('sections.pay.dueDay', [payMethod.dueDay]) }}</strong> <strong>{{ $t('sections.pay.dueDay', [payMethod.dueDay]) }}</strong>
</section> </section>
</p> </p>
<p v-if="payMethod.code == 'bankDraft'" <p v-if="payMethod.code == 'bankDraft'" v-html="$t('sections.pay.accountImplicates', [accountAddress])">
v-html="$t('sections.pay.accountImplicates', [accountAddress])"> </p>
</p> <p v-else-if="payMethod.code == 'card'">
<p v-else-if="payMethod.code == 'card'"> {{ $t('sections.pay.cardImplicates') }}
{{ $t('sections.pay.cardImplicates') }} </p>
</p>
<p>{{ $t('notifyAnError') }}</p> <p>{{ $t('notifyAnError') }}</p>
</div> </div>
</div> </div>
<!-- Footer block --> </email-body>
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,6 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'payment-update', name: 'payment-update',
@ -21,8 +20,7 @@ module.exports = {
} }
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build()
}, },
props: { props: {
id: { id: {

View File

@ -1,90 +1,49 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('description.dear')}},</p>
<title>{{ $t('subject') }}</title> <p>{{$t('description.instructions')}}</p>
</head> <p v-html="$t('description.followGuide')"></p>
<body> <p v-html="$t('description.downloadFrom')"></p>
<table class="grid"> <p v-html="$t('description.downloadDriver')"></p>
<tbody>
<tr>
<td>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('description.dear')}},</p>
<p>{{$t('description.instructions')}}</p>
<p v-html="$t('description.followGuide')"></p>
<p v-html="$t('description.downloadFrom')"></p>
<p v-html="$t('description.downloadDriver')"></p>
<h1>{{$t('sections.QLabel.title')}}</h1> <h1>{{$t('sections.QLabel.title')}}</h1>
<p>{{$t('sections.QLabel.description')}}:</p> <p>{{$t('sections.QLabel.description')}}:</p>
<ol> <ol>
<li v-for="step in $t('sections.QLabel.steps')"> <li v-for="step in $t('sections.QLabel.steps')">
<span v-html="step"></span> <span v-html="step"></span>
</li> </li>
</ol> </ol>
</div> </div>
</div> </div>
<!-- Block --> <div class="grid-row">
<div class="grid-row"> <div class="grid-block vn-pa-ml">
<div class="grid-block vn-pa-ml"> <h1>{{$t('sections.help.title')}}</h1>
<h1>{{$t('sections.help.title')}}</h1> <p>{{$t('sections.help.description')}}</p>
<p>{{$t('sections.help.description')}}</p> <p v-html="$t('sections.help.remoteSupport')"></p>
<p v-html="$t('sections.help.remoteSupport')"></p> </div>
</div> </div>
</div> <div class="grid-row">
<!-- Block --> <div class="grid-block vn-pa-ml">
<div class="grid-row"> <div v-if="client.salesPersonName">
<div class="grid-block vn-pa-ml"> {{$t('salesPersonName')}}: <strong>{{client.salesPersonName}}</strong>
<div v-if="client.salesPersonName"> </div>
{{$t('salesPersonName')}}: <strong>{{client.salesPersonName}}</strong> <div v-if="client.salesPersonPhone">
</div> {{$t('salesPersonPhone')}}: <strong>{{client.salesPersonPhone}}</strong>
<div v-if="client.salesPersonPhone"> </div>
{{$t('salesPersonPhone')}}: <strong>{{client.salesPersonPhone}}</strong> <div v-if="client.salesPersonEmail">
</div> {{$t('salesPersonEmail')}}:
<div v-if="client.salesPersonEmail"> <strong><a v-bind:href="`mailto:${client.salesPersonEmail}`"
{{$t('salesPersonEmail')}}: target="_blank">{{client.salesPersonEmail}}</strong>
<strong><a v-bind:href="`mailto:${client.salesPersonEmail}`" target="_blank">{{client.salesPersonEmail}}</strong> </div>
</div> </div>
</div> </div>
</div> <div class="grid-row" v-if="isPreview">
<!-- Block --> <div class="grid-block vn-pa-ml">
<div class="grid-row" v-if="isPreview"> <attachment v-for="attachment in attachments" v-bind:key="attachment.filename"
<div class="grid-block vn-pa-ml"> v-bind:attachment="attachment" v-bind:args="$props">
<attachment v-for="attachment in attachments" </attachment>
v-bind:key="attachment.filename" </div>
v-bind:attachment="attachment" </div>
v-bind:args="$props"> </email-body>
</attachment>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,6 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
const attachment = new Component('attachment'); const attachment = new Component('attachment');
const attachments = require('./attachments.json'); const attachments = require('./attachments.json');
@ -18,8 +17,7 @@ module.exports = {
} }
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build(),
'email-footer': emailFooter.build(),
'attachment': attachment.build() 'attachment': attachment.build()
}, },
props: { props: {

View File

@ -1,57 +1,21 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('description.dear')}},</p>
<title>{{ $t('subject') }}</title> <div v-html="$t('description.instructions')"></div>
</head> <p>{{$t('description.conclusion')}}</p>
<body> </div>
<table class="grid"> </div>
<tbody> <div class="grid-row" v-if="isPreview">
<tr> <div class="grid-block vn-pa-ml">
<td> <attachment
<!-- Empty block --> v-for="attachment in attachments"
<div class="grid-row"> v-bind:key="attachment.filename"
<div class="grid-block empty"></div> v-bind:attachment="attachment"
</div> v-bind:args="$props"
<!-- Header block --> >
<div class="grid-row"> </attachment>
<div class="grid-block"> </div>
<email-header v-bind="$props"></email-header> </div>
</div> </email-body>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('description.dear')}},</p>
<div v-html="$t('description.instructions')"></div>
<p>{{$t('description.conclusion')}}</p>
</div>
</div>
<!-- Attachments block -->
<div class="grid-row" v-if="isPreview">
<div class="grid-block vn-pa-ml">
<attachment v-for="attachment in attachments"
v-bind:key="attachment.filename"
v-bind:attachment="attachment"
v-bind:args="$props">
</attachment>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,7 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
const attachment = new Component('attachment');
const attachments = require('./attachments.json'); const attachments = require('./attachments.json');
module.exports = { module.exports = {
@ -10,9 +8,7 @@ module.exports = {
return {attachments}; return {attachments};
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build()
'email-footer': emailFooter.build(),
'attachment': attachment.build()
}, },
props: { props: {
id: { id: {

View File

@ -1,46 +1,9 @@
<!DOCTYPE html> <email-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<head> <div class="grid-block vn-pa-ml">
<meta name="viewport" content="width=device-width"> <h1>{{ $t('title') }}</h1>
<meta name="format-detection" content="telephone=no"> <p>{{$t('dear')}},</p>
<title>{{ $t('subject') }}</title> <p v-html="$t('description', [minDate, maxDate])"></p>
</head> </div>
<body> </div>
<table class="grid"> </email-body>
<tbody>
<tr>
<td>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
<!-- Header block -->
<div class="grid-row">
<div class="grid-block">
<email-header v-bind="$props"></email-header>
</div>
</div>
<!-- Block -->
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('dear')}},</p>
<p v-html="$t('description', [minDate, maxDate])"></p>
</div>
</div>
<!-- Footer block -->
<div class="grid-row">
<div class="grid-block">
<email-footer v-bind="$props"></email-footer>
</div>
</div>
<!-- Empty block -->
<div class="grid-row">
<div class="grid-block empty"></div>
</div>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -1,6 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const emailHeader = new Component('email-header'); const emailBody = new Component('email-body');
const emailFooter = new Component('email-footer');
module.exports = { module.exports = {
name: 'supplier-campaign-metrics', name: 'supplier-campaign-metrics',
@ -16,8 +15,7 @@ module.exports = {
} }
}, },
components: { components: {
'email-header': emailHeader.build(), 'email-body': emailBody.build()
'email-footer': emailFooter.build()
}, },
props: { props: {
id: { id: {

View File

@ -0,0 +1,31 @@
<report-body v-bind="$props">
<div class="grid-row">
<div class="grid-block">
<div class="columns">
<div class="size50">
<p style="text-align: right">{{$t('Place')}} {{currentDate()}}</p>
<h3 style="text-align: center; margin-top: 8%">{{$t('Compensation') | uppercase}}</h3>
<p style="margin-top: 8%">{{$t('In one hand')}}:</p>
<p style="text-align: justify">
{{company.name}} {{$t('CIF')}} {{company.nif}} {{$t('Home')}} {{company.street}},
{{company.city}}.
</p>
<p style="margin-top: 5%">{{$t('In other hand')}}:</p>
<p style="text-align: justify">
{{$t('Sr')}} {{client.name}} {{$t('NIF')}} {{client.fi}} {{$t('Home')}} {{client.street}},
{{client.city}}.
</p>
<h4 style="text-align: center; margin-top: 10%">{{$t('Agree') | uppercase}}</h4>
<p style="margin-top: 8%; text-align: justify">
{{$t('Date')}} {{client.payed | date('%d-%m-%Y')}} {{$t('Compensate')}} {{client.amountPaid}} €
{{$t('From client')}} {{client.name}} {{$t('Toclient')}} {{company.name}}.
</p>
<p style="margin-top: 8%">
{{$t('Reception')}} <span style="color: blue">administracion@verdnatura.es</span>
</p>
<div style="margin-top: 8%"><small>{{$t('Greetings')}}</small></div>
</div>
</div>
</div>
</div>
</report-body>

View File

@ -0,0 +1,34 @@
const Component = require(`vn-print/core/component`);
const reportBody = new Component('report-body');
module.exports = {
name: 'balance-compensation',
async serverPrefetch() {
this.client = await this.fetchClient(this.id);
this.company = await this.fetchCompany(this.id);
},
methods: {
fetchClient(id) {
return this.findOneFromDef('client', [id]);
},
fetchCompany(id) {
return this.findOneFromDef('company', [id]);
},
currentDate() {
const current = new Date();
const date = `${current.getDate()}/${current.getMonth() + 1}/${current.getFullYear()}`;
return date;
}
},
components: {
'report-body': reportBody.build()
},
props: {
id: {
type: Number,
required: true,
description: 'The receipt id'
}
}
};

View File

@ -0,0 +1,12 @@
const Stylesheet = require(`vn-print/core/stylesheet`);
const path = require('path');
const vnPrintPath = path.resolve('print');
module.exports = new Stylesheet([
`${vnPrintPath}/common/css/spacing.css`,
`${vnPrintPath}/common/css/misc.css`,
`${vnPrintPath}/common/css/layout.css`,
`${vnPrintPath}/common/css/report.css`,
`${__dirname}/style.css`])
.mergeStyles();

View File

@ -0,0 +1,16 @@
reportName: compensacion-saldo
Place: Algemesí, a
Compensation: Compensación de saldos deudores y acreedores
In one hand: De una parte
CIF: con CIF
NIF: con NIF
Home: y domicilio sito en
In other hand: De la otra
Sr: Don/Doña
Agree: Acuerdan
Date: En fecha de
Compensate: se ha compensado el saldo de
From client: del cliente/proveedor
To client: con el cliente/proveedor
Reception: Por favor, rogamos confirmen la recepción de esta compensación al email
Greetings: Saludos cordiales,

View File

@ -0,0 +1,12 @@
SELECT
c.name,
c.socialName,
c.street,
c.fi,
c.city,
r.amountPaid,
r.payed
FROM client c
JOIN receipt r ON r.clientFk = c.id
JOIN supplier s ON c.fi = s.nif
WHERE r.id = ?

View File

@ -0,0 +1,8 @@
SELECT
s.name,
s.nif,
s.street,
s.city
FROM supplier s
JOIN receipt r ON r.companyFk = s.id
WHERE r.id = ?;

View File

@ -1,95 +1,72 @@
<!DOCTYPE html> <report-body v-bind="$props">
<html v-bind:lang="$i18n.locale"> <div class="grid-row">
<body> <div class="grid-block">
<table class="grid"> <div class="columns">
<tbody> <div class="size50">
<tr> <h1 class="title uppercase">{{$t('title')}}</h1>
<td> <div class="size75">
<!-- Header block --> <table class="row-oriented report-info">
<report-header v-bind="$props"></report-header> <tbody>
<!-- Block --> <tr>
<div class="grid-row"> <td class="font gray">{{$t('Client')}}</td>
<div class="grid-block"> <th>{{client.id}}</th>
<div class="columns"> </tr>
<div class="size50"> <tr>
<h1 class="title uppercase">{{$t('title')}}</h1> <td class="font gray">{{$t('From')}}</td>
<div class="size75"> <th>{{from | date('%d-%m-%Y')}}</th>
<table class="row-oriented report-info"> </tr>
<tbody> <tr>
<tr> <td class="font gray">{{$t('To')}}</td>
<td class="font gray">{{$t('Client')}}</td> <th>{{to | date('%d-%m-%Y')}}</th>
<th>{{client.id}}</th> </tr>
</tr> </tbody>
<tr> </table>
<td class="font gray">{{$t('From')}}</td> </div>
<th>{{from | date('%d-%m-%Y')}}</th> </div>
</tr> <div class="size50">
<tr> <div class="panel">
<td class="font gray">{{$t('To')}}</td> <div class="header">{{$t('clientData')}}</div>
<th>{{to | date('%d-%m-%Y')}}</th> <div class="body">
</tr> <h3 class="uppercase">{{client.socialName}}</h3>
</tbody> <div>{{client.street}}</div>
</table> <div>{{client.postcode}}, {{client.city}} ({{client.province}})</div>
</div> <div>{{client.country}}</div>
</div>
<div class="size50">
<div class="panel">
<div class="header">{{$t('clientData')}}</div>
<div class="body">
<h3 class="uppercase">{{client.socialName}}</h3>
<div>
{{client.street}}
</div>
<div>
{{client.postcode}}, {{client.city}} ({{client.province}})
</div>
<div>
{{client.country}}
</div>
</div>
</div>
</div>
</div>
<table class="column-oriented">
<thead>
<tr>
<th>{{$t('Code')}}</th>
<th class="number">{{$t('Quantity')}}</th>
<th width="50%">{{$t('Concept')}}</th>
</tr>
</thead>
<tbody v-for="sale in sales">
<tr>
<td>{{sale.itemFk | zerofill('000000')}}</td>
<td class="number">{{Math.trunc(sale.subtotal)}}</td>
<td width="50%">{{sale.concept}}</td>
</tr>
<tr class="description font light-gray">
<td colspan="7">
<span v-if="sale.value5">
<strong>{{sale.tag5}}</strong> {{sale.value5}}
</span>
<span v-if="sale.value6">
<strong>{{sale.tag6}}</strong> {{sale.value6}}
</span>
<span v-if="sale.value7">
<strong>{{sale.tag7}}</strong> {{sale.value7}}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div> </div>
<!-- Footer block --> </div>
<report-footer id="pageFooter" </div>
v-bind:left-text="$t('client', [client.id])" </div>
v-bind:center-text="client.socialName" <table class="column-oriented">
v-bind="$props"> <thead>
</report-footer> <tr>
</td> <th>{{$t('Code')}}</th>
</tr> <th class="number">{{$t('Quantity')}}</th>
</tbody> <th width="50%">{{$t('Concept')}}</th>
</table> </tr>
</body> </thead>
</html> <tbody v-for="sale in sales">
<tr>
<td>{{sale.itemFk | zerofill('000000')}}</td>
<td class="number">{{Math.trunc(sale.subtotal)}}</td>
<td width="50%">{{sale.concept}}</td>
</tr>
<tr class="description font light-gray">
<td colspan="7">
<span v-if="sale.value5"> <strong>{{sale.tag5}}</strong> {{sale.value5}} </span>
<span v-if="sale.value6"> <strong>{{sale.tag6}}</strong> {{sale.value6}} </span>
<span v-if="sale.value7"> <strong>{{sale.tag7}}</strong> {{sale.value7}} </span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<template v-slot:footer>
<report-footer
id="pageFooter"
v-bind:left-text="$t('client', [client.id])"
v-bind:center-text="client.socialName"
v-bind="$props"
>
</report-footer>
</template>
</report-body>

View File

@ -1,5 +1,5 @@
const Component = require(`vn-print/core/component`); const Component = require(`vn-print/core/component`);
const reportHeader = new Component('report-header'); const reportBody = new Component('report-body');
const reportFooter = new Component('report-footer'); const reportFooter = new Component('report-footer');
module.exports = { module.exports = {
@ -20,7 +20,7 @@ module.exports = {
}, },
}, },
components: { components: {
'report-header': reportHeader.build(), 'report-body': reportBody.build(),
'report-footer': reportFooter.build() 'report-footer': reportFooter.build()
}, },
props: { props: {

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