Updated to vue3
gitea/salix/pipeline/head There was a failure building this commit
Details
gitea/salix/pipeline/head There was a failure building this commit
Details
This commit is contained in:
parent
163f7fd284
commit
0cd5f852e2
|
@ -0,0 +1,23 @@
|
|||
const db = require('vn-print/core/database');
|
||||
|
||||
function useDatabase() {
|
||||
function rawSql(query, params, connection) {
|
||||
return db.rawSql(query, params, connection);
|
||||
}
|
||||
|
||||
function findOne(query, params) {
|
||||
return db.findOne(query, params);
|
||||
}
|
||||
|
||||
function findValue(query, params) {
|
||||
return db.findValue(query, params);
|
||||
}
|
||||
|
||||
return {
|
||||
rawSql,
|
||||
findOne,
|
||||
findValue
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {useDatabase};
|
|
@ -9,7 +9,8 @@
|
|||
"i18n": {
|
||||
"locale": "es",
|
||||
"fallbackLocale": "es",
|
||||
"silentTranslationWarn": false
|
||||
"silentTranslationWarn": false,
|
||||
"allowComposition": true
|
||||
},
|
||||
"pdf": {
|
||||
"format": "A4",
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
const Vue = require('vue');
|
||||
const VueI18n = require('vue-i18n');
|
||||
const renderer = require('vue-server-renderer').createRenderer();
|
||||
Vue.use(VueI18n);
|
||||
const {createSSRApp, h} = require('vue');
|
||||
const {createI18n} = require('vue-i18n');
|
||||
const {renderToString} = require('vue/server-renderer');
|
||||
|
||||
const fs = require('fs');
|
||||
const yaml = require('js-yaml');
|
||||
// const yaml = require('js-yaml');
|
||||
const juice = require('juice');
|
||||
const path = require('path');
|
||||
|
||||
const config = require('./config');
|
||||
const messages = require('vn-print/i18n');
|
||||
|
||||
class Component {
|
||||
constructor(name) {
|
||||
|
@ -25,53 +26,53 @@ class Component {
|
|||
return fs.readFileSync(fullPath, 'utf8');
|
||||
}
|
||||
|
||||
get locale() {
|
||||
if (!this._locale)
|
||||
this._locale = this.getLocales();
|
||||
// get locale() {
|
||||
// if (!this._locale)
|
||||
// this._locale = this.getLocales();
|
||||
|
||||
return this._locale;
|
||||
}
|
||||
// return this._locale;
|
||||
// }
|
||||
|
||||
getLocales() {
|
||||
const mergedLocales = {messages: {}};
|
||||
const localePath = path.resolve(__dirname, `${this.path}/locale`);
|
||||
// getLocales() {
|
||||
// const mergedLocales = {messages: {}};
|
||||
// const localePath = path.resolve(__dirname, `${this.path}/locale`);
|
||||
|
||||
if (!fs.existsSync(localePath))
|
||||
return mergedLocales;
|
||||
// if (!fs.existsSync(localePath))
|
||||
// return mergedLocales;
|
||||
|
||||
const localeDir = fs.readdirSync(localePath);
|
||||
for (const locale of localeDir) {
|
||||
const fullPath = path.join(localePath, '/', locale);
|
||||
const yamlLocale = fs.readFileSync(fullPath, 'utf8');
|
||||
const jsonLocale = yaml.safeLoad(yamlLocale);
|
||||
const localeName = locale.replace('.yml', '');
|
||||
// const localeDir = fs.readdirSync(localePath);
|
||||
// for (const locale of localeDir) {
|
||||
// const fullPath = path.join(localePath, '/', locale);
|
||||
// const yamlLocale = fs.readFileSync(fullPath, 'utf8');
|
||||
// const jsonLocale = yaml.safeLoad(yamlLocale);
|
||||
// const localeName = locale.replace('.yml', '');
|
||||
|
||||
mergedLocales.messages[localeName] = jsonLocale;
|
||||
}
|
||||
// mergedLocales.messages[localeName] = jsonLocale;
|
||||
// }
|
||||
|
||||
return mergedLocales;
|
||||
}
|
||||
// return mergedLocales;
|
||||
// }
|
||||
|
||||
async getUserLocale() {
|
||||
let lang = this.args.lang;
|
||||
// async getUserLocale() {
|
||||
// let lang = this.args.lang;
|
||||
|
||||
// Fetches user locale from mixing method getLocale()
|
||||
if (this.args.recipientId) {
|
||||
const component = await this.component();
|
||||
lang = await component.getLocale(this.args.recipientId);
|
||||
}
|
||||
// // Fetches user locale from mixing method getLocale()
|
||||
// if (this.args.recipientId) {
|
||||
// const component = await this.component();
|
||||
// lang = await component.getLocale(this.args.recipientId);
|
||||
// }
|
||||
|
||||
const messages = this.locale.messages;
|
||||
const userTranslations = messages[lang];
|
||||
// const messages = this.locale.messages;
|
||||
// const userTranslations = messages[lang];
|
||||
|
||||
if (!userTranslations) {
|
||||
const fallbackLang = config.i18n.fallbackLocale;
|
||||
// if (!userTranslations) {
|
||||
// const fallbackLang = config.i18n.fallbackLocale;
|
||||
|
||||
return messages[fallbackLang];
|
||||
}
|
||||
// return messages[fallbackLang];
|
||||
// }
|
||||
|
||||
return userTranslations;
|
||||
}
|
||||
// return userTranslations;
|
||||
// }
|
||||
|
||||
get stylesheet() {
|
||||
let mergedStyles = '';
|
||||
|
@ -99,7 +100,7 @@ class Component {
|
|||
throw new Error(`Template "${this.name}" not found`);
|
||||
|
||||
const component = require(`${this.path}/${this.name}`);
|
||||
component.i18n = this.locale;
|
||||
|
||||
component.attachments = this.attachments;
|
||||
component.template = juice.inlineContent(this.template, this.stylesheet, {
|
||||
inlinePseudoElements: true
|
||||
|
@ -118,15 +119,22 @@ class Component {
|
|||
return this._component;
|
||||
|
||||
const component = this.build();
|
||||
const i18n = new VueI18n(config.i18n);
|
||||
|
||||
const i18nOptions = Object.assign({
|
||||
messages: messages
|
||||
}, config.i18n);
|
||||
|
||||
const i18n = createI18n(i18nOptions);
|
||||
const props = {...this.args};
|
||||
this._component = new Vue({
|
||||
const app = createSSRApp({
|
||||
i18n: i18n,
|
||||
render: h => h(component, {
|
||||
props: props
|
||||
})
|
||||
render: () => h(component, props)
|
||||
});
|
||||
|
||||
app.use(i18n);
|
||||
|
||||
this._component = app;
|
||||
|
||||
return this._component;
|
||||
}
|
||||
|
||||
|
@ -134,7 +142,7 @@ class Component {
|
|||
* @return {Promise} Rendered component
|
||||
*/
|
||||
async render() {
|
||||
return renderer.renderToString(
|
||||
return renderToString(
|
||||
this.component()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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/email.css`,
|
||||
`${__dirname}/style.css`])
|
||||
.mergeStyles();
|
|
@ -0,0 +1,19 @@
|
|||
body {
|
||||
-webkit-text-size-adjust: none;
|
||||
-ms-text-size-adjust: none;
|
||||
background-color: #FFF;
|
||||
font-weight: 400;
|
||||
color: #555;
|
||||
margin: 0
|
||||
}
|
||||
|
||||
body {
|
||||
zoom: 0.70;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-bottom: 20px;
|
||||
font-weight: 100;
|
||||
font-size: 2.6rem;
|
||||
margin-top: 0
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
test
|
|
@ -0,0 +1,8 @@
|
|||
const controller = {
|
||||
template: '<div><slot/></div>',
|
||||
setup() {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = controller;
|
|
@ -1,8 +0,0 @@
|
|||
// Import global filters
|
||||
require('./date');
|
||||
require('./uppercase');
|
||||
require('./currency');
|
||||
require('./percentage');
|
||||
require('./number');
|
||||
require('./zerofill');
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// Import global mixins
|
||||
require('./image-src');
|
||||
require('./user-locale');
|
||||
require('./prop-validator');
|
||||
require('./db-helper');
|
||||
// require('./image-src');
|
||||
// require('./user-locale');
|
||||
// require('./prop-validator');
|
||||
// require('./db-helper');
|
||||
|
|
|
@ -18,9 +18,9 @@ class Report extends Component {
|
|||
return `../templates/reports/${this.name}`;
|
||||
}
|
||||
|
||||
async getName() {
|
||||
return (await this.getUserLocale())['reportName'];
|
||||
}
|
||||
// async getName() {
|
||||
// return (await this.getUserLocale())['reportName'];
|
||||
// }
|
||||
|
||||
async toPdfStream() {
|
||||
const template = await this.render();
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// Import global filters
|
||||
// require('./date');
|
||||
// require('./uppercase');
|
||||
// require('./currency');
|
||||
// require('./percentage');
|
||||
// require('./number');
|
||||
// require('./zerofill');
|
||||
|
||||
module.exports = {
|
||||
toDate: require('./toDate'),
|
||||
toCurrency: require('./toCurrency')
|
||||
};
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
const Vue = require('vue');
|
||||
const config = require('../config');
|
||||
const config = require('../core/config');
|
||||
const defaultLocale = config.i18n.locale;
|
||||
|
||||
const percentage = function(value, minFraction = 2, maxFraction = 2, locale = defaultLocale) {
|
|
@ -1,5 +1,4 @@
|
|||
const Vue = require('vue');
|
||||
const config = require('../config');
|
||||
const config = require('vn-print/core/config');
|
||||
const defaultLocale = config.i18n.locale;
|
||||
|
||||
const currency = function(value, currency = 'EUR', locale = defaultLocale) {
|
||||
|
@ -9,6 +8,4 @@ const currency = function(value, currency = 'EUR', locale = defaultLocale) {
|
|||
}).format(parseFloat(value));
|
||||
};
|
||||
|
||||
Vue.filter('currency', currency);
|
||||
|
||||
module.exports = currency;
|
|
@ -1,4 +1,3 @@
|
|||
const Vue = require('vue');
|
||||
const strftime = require('strftime');
|
||||
|
||||
const date = function(value, specifiers = '%d-%m-%Y') {
|
||||
|
@ -6,6 +5,4 @@ const date = function(value, specifiers = '%d-%m-%Y') {
|
|||
return strftime(specifiers, value);
|
||||
};
|
||||
|
||||
Vue.filter('date', date);
|
||||
|
||||
module.exports = date;
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
deliveryNote: {
|
||||
title: 'test'
|
||||
}
|
||||
};
|
|
@ -0,0 +1,62 @@
|
|||
module.exports = {
|
||||
deliveryNote: {
|
||||
deliveryNote: 'Albarán',
|
||||
proforma: 'Proforma',
|
||||
withoutPrices: 'Albarán',
|
||||
clientId: 'Cliente',
|
||||
deliveryAddress: 'Dirección de entrega',
|
||||
fiscalData: 'Datos fiscales',
|
||||
saleLines: 'Líneas de pedido',
|
||||
date: 'Fecha',
|
||||
reference: 'Ref.',
|
||||
quantity: 'Cant.',
|
||||
concept: 'Concepto',
|
||||
price: 'PVP/u',
|
||||
discount: 'Dto.',
|
||||
vat: 'IVA',
|
||||
amount: 'Importe',
|
||||
total: 'Total',
|
||||
subtotal: 'Subtotal',
|
||||
vatType: 'Tipo de IVA',
|
||||
digitalSignature: 'Firma digital',
|
||||
ticket: 'Albarán {0}',
|
||||
plantPassport: 'Pasaporte fitosanitario',
|
||||
packages: 'Bultos',
|
||||
services:
|
||||
{
|
||||
title: 'Servicios',
|
||||
theader: {
|
||||
quantity: 'Cantidad',
|
||||
concept: 'Concepto',
|
||||
price: 'PVP/u',
|
||||
vat: 'IVA',
|
||||
amount: 'Importe'
|
||||
},
|
||||
tfoot: {subtotal: 'Subtotal'},
|
||||
warning: `Los embalajes en depósito se facturarán
|
||||
si no han sido devueltos pasados 30 dias de su entrega.`
|
||||
},
|
||||
packagings: {
|
||||
title: 'Cubos y embalajes',
|
||||
theader: {
|
||||
reference: 'Referencia',
|
||||
quantity: 'Cantidad',
|
||||
concept: 'Concepto'
|
||||
}
|
||||
},
|
||||
taxes: {
|
||||
title: 'Desglose impositivo',
|
||||
theader: {
|
||||
type: 'Tipo',
|
||||
taxBase: 'Base imp.',
|
||||
tax: 'Tasa',
|
||||
fee: 'Cuota'
|
||||
},
|
||||
tfoot: {
|
||||
subtotal: 'Subtotal',
|
||||
total: 'Total'
|
||||
}
|
||||
},
|
||||
observations: 'Observaciones'
|
||||
}
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
const en = require('./en');
|
||||
const es = require('./es');
|
||||
|
||||
module.exports = {
|
||||
en: en,
|
||||
es: es,
|
||||
};
|
|
@ -16,8 +16,6 @@ module.exports = {
|
|||
require('./core/database').init(app.dataSources);
|
||||
require('./core/smtp').init();
|
||||
require('./core/cluster').init();
|
||||
require('./core/mixins');
|
||||
require('./core/filters');
|
||||
|
||||
const componentsDir = fs.readdirSync(componentsPath);
|
||||
componentsDir.forEach(componentName => {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,8 +24,7 @@
|
|||
"puppeteer-cluster": "^0.23.0",
|
||||
"qrcode": "^1.4.2",
|
||||
"strftime": "^0.10.0",
|
||||
"vue": "^2.6.10",
|
||||
"vue-i18n": "^8.15.0",
|
||||
"vue-server-renderer": "^2.6.10"
|
||||
"vue": "^3.2.42",
|
||||
"vue-i18n": "^9.2.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,54 +2,334 @@
|
|||
<template v-slot:header>
|
||||
<report-header v-bind="$props" v-bind:company-code="ticket.companyCode"> </report-header>
|
||||
</template>
|
||||
<div class="grid-row">
|
||||
<div class="grid-block">
|
||||
<div class="columns">
|
||||
<div class="size50">
|
||||
<div class="size75 vn-mt-ml">
|
||||
<h1 class="title uppercase">{{$t(deliverNoteType)}}</h1>
|
||||
<table class="row-oriented ticket-info">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t('clientId')}}</td>
|
||||
<th>{{client.id}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t(deliverNoteType)}}</td>
|
||||
<th>{{ticket.id}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t('date')}}</td>
|
||||
<th>{{ticket.shipped | date('%d-%m-%Y')}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t('packages')}}</td>
|
||||
<th>{{ticket.packages}}</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="size50">
|
||||
<div class="panel">
|
||||
<div class="header">{{$t('deliveryAddress')}}</div>
|
||||
<div class="body">
|
||||
<h3 class="uppercase">{{address.nickname}}</h3>
|
||||
<div>{{address.street}}</div>
|
||||
<div>{{address.postalCode}}, {{address.city}} ({{address.province}})</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid-row">
|
||||
<div class="grid-block">
|
||||
<div class="columns">
|
||||
<div class="size50">
|
||||
<div class="size75 vn-mt-ml">
|
||||
<h1 class="title uppercase">{{$t(`deliveryNote['${deliverNoteType}']`)}}</h1>
|
||||
<table class="row-oriented ticket-info">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t('deliveryNote.clientId')}}</td>
|
||||
<th>{{client.id}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t(`deliveryNote['${deliverNoteType}']`)}}</td>
|
||||
<th>{{ticket.id}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t('deliveryNote.date')}}</td>
|
||||
<th>{{ticket.shipped | toDate('%d-%m-%Y')}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t('deliveryNote.packages')}}</td>
|
||||
<th>{{ticket.packages}}</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="size50">
|
||||
<div class="panel">
|
||||
<div class="header">{{$t('deliveryNote.deliveryAddress')}}</div>
|
||||
<div class="body">
|
||||
<h3 class="uppercase">{{address.nickname}}</h3>
|
||||
<div>
|
||||
{{address.street}}
|
||||
</div>
|
||||
<div>
|
||||
{{address.postalCode}}, {{address.city}} ({{address.province}})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="header">{{$t('fiscalData')}}</div>
|
||||
<div class="body">
|
||||
<div>{{client.socialName}}</div>
|
||||
<div>{{client.street}}</div>
|
||||
<div>{{client.fi}}</div>
|
||||
<div class="panel">
|
||||
<div class="header">{{$t('deliveryNote.fiscalData')}}</div>
|
||||
<div class="body">
|
||||
<div>
|
||||
{{client.socialName}}
|
||||
</div>
|
||||
<div>
|
||||
{{client.street}}
|
||||
</div>
|
||||
<div>
|
||||
{{client.fi}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>{{$t('deliveryNote.saleLines')}}</h2>
|
||||
<table v-if="sales" class="column-oriented">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="5%">
|
||||
{{$t('deliveryNote.reference')}}
|
||||
</th>
|
||||
<th class="number">
|
||||
{{$t('deliveryNote.quantity')}}
|
||||
</th>
|
||||
<th width="50%">
|
||||
{{$t('deliveryNote.concept')}}
|
||||
</th>
|
||||
<th class="number" v-if="showPrices">
|
||||
{{$t('deliveryNote.price')}}
|
||||
</th>
|
||||
<th class="centered" width="5%" v-if="showPrices">
|
||||
{{$t('deliveryNote.discount')}}
|
||||
</th>
|
||||
<th class="centered" v-if="showPrices">
|
||||
{{$t('deliveryNote.vat')}}
|
||||
</th>
|
||||
<th class="number" v-if="showPrices">
|
||||
{{$t('deliveryNote.amount')}}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody v-for="sale in sales" class="no-page-break">
|
||||
<tr>
|
||||
<td width="5%">{{sale.itemFk}}</td>
|
||||
<td class="number">{{sale.quantity}}</td>
|
||||
<td width="50%">{{sale.concept}}</td>
|
||||
<td class="number" v-if="showPrices">
|
||||
{{toCurrency(sale.price, 'EUR', $i18n.locale)}}
|
||||
</td>
|
||||
<td class="centered" width="5%" v-if="showPrices">{{(sale.discount / 100) |
|
||||
percentage}}</td>
|
||||
<td class="centered" v-if="showPrices">{{sale.vatType}}</td>
|
||||
<td class="number" v-if="showPrices">
|
||||
{{toCurrency(sale.price * sale.quantity * (1 - sale.discount / 100), 'EUR', $i18n.locale)}}
|
||||
</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>
|
||||
<tfoot v-if="showPrices">
|
||||
<tr>
|
||||
<td colspan="6" class="font bold">
|
||||
<span class="pull-right">{{$t('deliveryNote.subtotal')}}</span>
|
||||
</td>
|
||||
<td class="number">{{toCurrency(getSubTotal(), 'EUR', $i18n.locale)}}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<!-- <div class="columns vn-mb-ml">
|
||||
<div class="size100 no-page-break" v-if="services.length > 0">
|
||||
<h2>{{$t('services.title')}}</h2>
|
||||
<table class="column-oriented">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="5%"></th>
|
||||
<th class="number">{{$t('services.theader.quantity')}}</th>
|
||||
<th width="50%">{{$t('services.theader.concept')}}</th>
|
||||
<th class="number">{{$t('services.theader.price')}}</th>
|
||||
<th class="centered" width="5%"></th>
|
||||
<th class="centered">{{$t('services.theader.vat')}}</th>
|
||||
<th class="number">{{$t('services.theader.amount')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="service in services">
|
||||
<td width="5%"></td>
|
||||
<td class="number">{{service.quantity}}</td>
|
||||
<td width="50%">{{service.description}}</td>
|
||||
<td class="number">{{service.price | toCurrency('EUR', $i18n.locale)}}
|
||||
</td>
|
||||
<td class="centered" width="5%"></td>
|
||||
<td class="centered">{{service.taxDescription}}</td>
|
||||
<td class="number">{{service.price | toCurrency('EUR', $i18n.locale)}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="6" class="font bold">
|
||||
<span class="pull-right">{{$t('services.tfoot.subtotal')}}</span>
|
||||
</td>
|
||||
<td class="number">{{serviceTotal | toCurrency('EUR', $i18n.locale)}}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<span class="font gray">* {{ $t('services.warning') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div id="packagings" class="size100 no-page-break" v-if="packagings.length > 0">
|
||||
<h2>{{$t('packagings.title')}}</h2>
|
||||
<table class="column-oriented">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{$t('packagings.theader.reference')}}</th>
|
||||
<th class="number">{{$t('packagings.theader.quantity')}}</th>
|
||||
<th wihth="75%">{{$t('packagings.theader.concept')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="packaging in packagings">
|
||||
<td>{{packaging.itemFk | zerofill('000000')}}</td>
|
||||
<td class="number">{{packaging.quantity}}</td>
|
||||
<td width="85%">{{packaging.name}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns vn-mt-xl" v-if="showPrices">
|
||||
<div id="taxes" class="size50 pull-right no-page-break" v-if="taxes">
|
||||
<table class="column-oriented">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="4">{{$t('taxes.title')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<thead class="light">
|
||||
<tr>
|
||||
<th width="45%">{{$t('taxes.theader.type')}}</th>
|
||||
<th width="25%" class="number">{{$t('taxes.theader.taxBase')}}</th>
|
||||
<th>{{$t('taxes.theader.tax')}}</th>
|
||||
<th class="number">{{$t('taxes.theader.fee')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="tax in taxes">
|
||||
<td width="45%">{{tax.name}}</td>
|
||||
<td width="25%" class="number">
|
||||
{{tax.Base | currency('EUR', $i18n.locale)}}
|
||||
</td>
|
||||
<td>{{tax.vatPercent | percentage}}</td>
|
||||
<td class="number">{{tax.tax | currency('EUR', $i18n.locale)}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="font bold">
|
||||
<td width="45%">{{$t('subtotal')}}</td>
|
||||
<td width="20%" class="number">
|
||||
{{getTotalBase() | currency('EUR', $i18n.locale)}}
|
||||
</td>
|
||||
<td></td>
|
||||
<td class="number">{{getTotalTax()| currency('EUR', $i18n.locale)}}</td>
|
||||
</tr>
|
||||
<tr class="font bold">
|
||||
<td colspan="2">{{$t('total')}}</td>
|
||||
<td colspan="2" class="number">{{getTotal() | currency('EUR',
|
||||
$i18n.locale)}}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="phytosanitary" class="size50 pull-left no-page-break">
|
||||
<div class="panel">
|
||||
<div class="body">
|
||||
<div class="flag">
|
||||
<div class="columns">
|
||||
<div class="size25">
|
||||
<img v-bind:src="getReportSrc('europe.png')" />
|
||||
</div>
|
||||
<div class="size75 flag-text">
|
||||
<strong>{{$t('plantPassport')}}</strong><br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="phytosanitary-info">
|
||||
<div>
|
||||
<strong>A</strong>
|
||||
<span>{{getBotanical()}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>B</strong>
|
||||
<span>ES17462130</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>C</strong>
|
||||
<span>{{ticket.id}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>D</strong>
|
||||
<span>ES</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="size50 pull-left no-page-break">
|
||||
<div id="signature" class="panel" v-if="signature && signature.id">
|
||||
<div class="header">{{$t('digitalSignature')}}</div>
|
||||
<div class="body centered">
|
||||
<img v-bind:src="dmsPath" />
|
||||
<div>{{signature.created | date('%d-%m-%Y')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns vn-mb-ml" v-if="hasObservations">
|
||||
<div class="size100 no-page-break">
|
||||
<h2>{{$t('observations')}}</h2>
|
||||
<p class="observations">{{ticket.description}}</p>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--
|
||||
</report-header>
|
||||
<div class="grid-row">
|
||||
<div class="grid-block">
|
||||
<div class="columns">
|
||||
<div class="size50">
|
||||
<div class="size75 vn-mt-ml">
|
||||
<h1 class="title uppercase">{{$t(deliverNoteType)}}</h1>
|
||||
<table class="row-oriented ticket-info">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t('clientId')}}</td>
|
||||
<th>{{client.id}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t(deliverNoteType)}}</td>
|
||||
<th>{{ticket.id}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t('date')}}</td>
|
||||
<th>{{ticket.shipped | date('%d-%m-%Y')}}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="font gray uppercase">{{$t('packages')}}</td>
|
||||
<th>{{ticket.packages}}</th>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="size50">
|
||||
<div class="panel">
|
||||
<div class="header">{{$t('deliveryAddress')}}</div>
|
||||
<div class="body">
|
||||
<h3 class="uppercase">{{address.nickname}}</h3>
|
||||
<div>
|
||||
{{address.street}}
|
||||
</div>
|
||||
<div>
|
||||
{{address.postalCode}}, {{address.city}} ({{address.province}})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>{{$t('saleLines')}}</h2>
|
||||
<table class="column-oriented">
|
||||
|
@ -203,48 +483,217 @@
|
|||
<div class="size75 flag-text"><strong>{{$t('plantPassport')}}</strong><br /></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="phytosanitary-info">
|
||||
<div>
|
||||
<strong>A</strong>
|
||||
<span>{{getBotanical()}}</span>
|
||||
|
||||
<h2>{{$t('saleLines')}}</h2>
|
||||
<table class="column-oriented">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="5%">{{$t('reference')}}</th>
|
||||
<th class="number">{{$t('quantity')}}</th>
|
||||
<th width="50%">{{$t('concept')}}</th>
|
||||
<th class="number" v-if="showPrices">{{$t('price')}}</th>
|
||||
<th class="centered" width="5%" v-if="showPrices">{{$t('discount')}}</th>
|
||||
<th class="centered" v-if="showPrices">{{$t('vat')}}</th>
|
||||
<th class="number" v-if="showPrices">{{$t('amount')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody v-for="sale in sales" class="no-page-break">
|
||||
<tr>
|
||||
<td width="5%">{{sale.itemFk | zerofill('000000')}}</td>
|
||||
<td class="number">{{sale.quantity}}</td>
|
||||
<td width="50%">{{sale.concept}}</td>
|
||||
<td class="number" v-if="showPrices">{{sale.price | currency('EUR',
|
||||
$i18n.locale)}}</td>
|
||||
<td class="centered" width="5%" v-if="showPrices">{{(sale.discount / 100) |
|
||||
percentage}}</td>
|
||||
<td class="centered" v-if="showPrices">{{sale.vatType}}</td>
|
||||
<td class="number" v-if="showPrices">{{sale.price * sale.quantity * (1 -
|
||||
sale.discount / 100) | currency('EUR', $i18n.locale)}}</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>
|
||||
<tfoot v-if="showPrices">
|
||||
<tr>
|
||||
<td colspan="6" class="font bold">
|
||||
<span class="pull-right">{{$t('subtotal')}}</span>
|
||||
</td>
|
||||
<td class="number">{{getSubTotal() | currency('EUR', $i18n.locale)}}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<div class="columns vn-mb-ml">
|
||||
<div class="size100 no-page-break" v-if="services.length > 0">
|
||||
<h2>{{$t('services.title')}}</h2>
|
||||
<table class="column-oriented">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="5%"></th>
|
||||
<th class="number">{{$t('services.theader.quantity')}}</th>
|
||||
<th width="50%">{{$t('services.theader.concept')}}</th>
|
||||
<th class="number">{{$t('services.theader.price')}}</th>
|
||||
<th class="centered" width="5%"></th>
|
||||
<th class="centered">{{$t('services.theader.vat')}}</th>
|
||||
<th class="number">{{$t('services.theader.amount')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="service in services">
|
||||
<td width="5%"></td>
|
||||
<td class="number">{{service.quantity}}</td>
|
||||
<td width="50%">{{service.description}}</td>
|
||||
<td class="number">{{service.price | currency('EUR', $i18n.locale)}}
|
||||
</td>
|
||||
<td class="centered" width="5%"></td>
|
||||
<td class="centered">{{service.taxDescription}}</td>
|
||||
<td class="number">{{service.price | currency('EUR', $i18n.locale)}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="6" class="font bold">
|
||||
<span class="pull-right">{{$t('services.tfoot.subtotal')}}</span>
|
||||
</td>
|
||||
<td class="number">{{serviceTotal | currency('EUR', $i18n.locale)}}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<span class="font gray">* {{ $t('services.warning') }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>B</strong>
|
||||
<span>ES17462130</span>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div id="packagings" class="size100 no-page-break" v-if="packagings.length > 0">
|
||||
<h2>{{$t('packagings.title')}}</h2>
|
||||
<table class="column-oriented">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{$t('packagings.theader.reference')}}</th>
|
||||
<th class="number">{{$t('packagings.theader.quantity')}}</th>
|
||||
<th wihth="75%">{{$t('packagings.theader.concept')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="packaging in packagings">
|
||||
<td>{{packaging.itemFk | zerofill('000000')}}</td>
|
||||
<td class="number">{{packaging.quantity}}</td>
|
||||
<td width="85%">{{packaging.name}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<strong>C</strong>
|
||||
<span>{{ticket.id}}</span>
|
||||
</div>
|
||||
<div class="columns vn-mt-xl" v-if="showPrices">
|
||||
<div id="taxes" class="size50 pull-right no-page-break" v-if="taxes">
|
||||
<table class="column-oriented">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="4">{{$t('taxes.title')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<thead class="light">
|
||||
<tr>
|
||||
<th width="45%">{{$t('taxes.theader.type')}}</th>
|
||||
<th width="25%" class="number">{{$t('taxes.theader.taxBase')}}</th>
|
||||
<th>{{$t('taxes.theader.tax')}}</th>
|
||||
<th class="number">{{$t('taxes.theader.fee')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="tax in taxes">
|
||||
<td width="45%">{{tax.name}}</td>
|
||||
<td width="25%" class="number">
|
||||
{{tax.Base | currency('EUR', $i18n.locale)}}
|
||||
</td>
|
||||
<td>{{tax.vatPercent | percentage}}</td>
|
||||
<td class="number">{{tax.tax | currency('EUR', $i18n.locale)}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="font bold">
|
||||
<td width="45%">{{$t('subtotal')}}</td>
|
||||
<td width="20%" class="number">
|
||||
{{getTotalBase() | currency('EUR', $i18n.locale)}}
|
||||
</td>
|
||||
<td></td>
|
||||
<td class="number">{{getTotalTax()| currency('EUR', $i18n.locale)}}</td>
|
||||
</tr>
|
||||
<tr class="font bold">
|
||||
<td colspan="2">{{$t('total')}}</td>
|
||||
<td colspan="2" class="number">{{getTotal() | currency('EUR',
|
||||
$i18n.locale)}}</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<strong>D</strong>
|
||||
<span>ES</span>
|
||||
|
||||
<div id="phytosanitary" class="size50 pull-left no-page-break">
|
||||
<div class="panel">
|
||||
<div class="body">
|
||||
<div class="flag">
|
||||
<div class="columns">
|
||||
<div class="size25">
|
||||
<img v-bind:src="getReportSrc('europe.png')" />
|
||||
</div>
|
||||
<div class="size75 flag-text">
|
||||
<strong>{{$t('plantPassport')}}</strong><br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="phytosanitary-info">
|
||||
<div>
|
||||
<strong>A</strong>
|
||||
<span>{{getBotanical()}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>B</strong>
|
||||
<span>ES17462130</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>C</strong>
|
||||
<span>{{ticket.id}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<strong>D</strong>
|
||||
<span>ES</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="size50 pull-left no-page-break">
|
||||
<div id="signature" class="panel" v-if="signature && signature.id">
|
||||
<div class="header">{{$t('digitalSignature')}}</div>
|
||||
<div class="body centered">
|
||||
<img v-bind:src="dmsPath" />
|
||||
<div>{{signature.created | date('%d-%m-%Y')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns vn-mb-ml" v-if="hasObservations">
|
||||
<div class="size100 no-page-break">
|
||||
<h2>{{$t('observations')}}</h2>
|
||||
<p class="observations">{{ticket.description}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns">
|
||||
<div class="size50 pull-left no-page-break">
|
||||
<div id="signature" class="panel" v-if="signature && signature.id">
|
||||
<div class="header">{{$t('digitalSignature')}}</div>
|
||||
<div class="body centered">
|
||||
<img v-bind:src="dmsPath" />
|
||||
<div>{{signature.created | date('%d-%m-%Y')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns vn-mb-ml" v-if="hasObservations">
|
||||
<div class="size100 no-page-break">
|
||||
<h2>{{$t('observations')}}</h2>
|
||||
<p class="observations">{{ticket.description}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template v-slot:footer>
|
||||
<template v-slot:footer>
|
||||
<report-footer
|
||||
id="pageFooter"
|
||||
v-bind:company-code="ticket.companyCode"
|
||||
|
@ -253,5 +702,5 @@
|
|||
v-bind="$props"
|
||||
>
|
||||
</report-footer>
|
||||
</template>
|
||||
</template>-->
|
||||
</report-body>
|
||||
|
|
|
@ -1,134 +1,21 @@
|
|||
const config = require(`vn-print/core/config`);
|
||||
const Component = require(`vn-print/core/component`);
|
||||
const reportBody = new Component('report-body');
|
||||
const reportHeader = new Component('report-header');
|
||||
const reportFooter = new Component('report-footer');
|
||||
const md5 = require('md5');
|
||||
const fs = require('fs-extra');
|
||||
// const config = require(`vn-print/core/config`);
|
||||
// const Component = require(`vn-print/core/component`);
|
||||
// const templateBody = new Component('template-body');
|
||||
// const reportHeader = new Component('report-header');
|
||||
// const reportFooter = new Component('report-footer');
|
||||
// const md5 = require('md5');
|
||||
// const fs = require('fs-extra');
|
||||
|
||||
module.exports = {
|
||||
name: 'delivery-note',
|
||||
async serverPrefetch() {
|
||||
this.client = await this.fetchClient(this.id);
|
||||
this.ticket = await this.fetchTicket(this.id);
|
||||
this.sales = await this.fetchSales(this.id);
|
||||
this.address = await this.fetchAddress(this.id);
|
||||
this.services = await this.fetchServices(this.id);
|
||||
this.taxes = await this.fetchTaxes(this.id);
|
||||
this.packagings = await this.fetchPackagings(this.id);
|
||||
this.signature = await this.fetchSignature(this.id);
|
||||
const {onServerPrefetch, ref, computed} = require('vue');
|
||||
const {useDatabase} = require('vn-print/composables/useDatabase');
|
||||
const reportHeader = require('vn-print/core/components/report-header/report-header');
|
||||
const reportBody = require('vn-print/core/components/report-body/report-body');
|
||||
const {toDate, toCurrency} = require('vn-print/filters');
|
||||
|
||||
if (!this.ticket)
|
||||
throw new Error('Something went wrong');
|
||||
},
|
||||
data() {
|
||||
return {totalBalance: 0.00};
|
||||
},
|
||||
computed: {
|
||||
dmsPath() {
|
||||
if (!this.signature) return;
|
||||
|
||||
const hash = md5(this.signature.id.toString()).substring(0, 3);
|
||||
const file = `${config.storage.root}/${hash}/${this.signature.id}.png`;
|
||||
|
||||
if (!fs.existsSync(file)) return null;
|
||||
|
||||
const src = fs.readFileSync(file);
|
||||
const base64 = Buffer.from(src, 'utf8').toString('base64');
|
||||
|
||||
return `data:image/png;base64, ${base64}`;
|
||||
},
|
||||
deliverNoteType() {
|
||||
return this.type ? this.type : 'deliveryNote';
|
||||
},
|
||||
serviceTotal() {
|
||||
let total = 0.00;
|
||||
this.services.forEach(service => {
|
||||
total += parseFloat(service.price) * service.quantity;
|
||||
});
|
||||
|
||||
return total;
|
||||
},
|
||||
showPrices() {
|
||||
return this.deliverNoteType != 'withoutPrices';
|
||||
},
|
||||
footerType() {
|
||||
const translatedType = this.$t(this.deliverNoteType);
|
||||
return `${translatedType} ${this.id}`;
|
||||
},
|
||||
hasObservations() {
|
||||
return this.ticket.description !== null;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchClient(id) {
|
||||
return this.findOneFromDef('client', [id]);
|
||||
},
|
||||
fetchTicket(id) {
|
||||
return this.findOneFromDef('ticket', [id]);
|
||||
},
|
||||
fetchAddress(id) {
|
||||
return this.findOneFromDef(`address`, [id]);
|
||||
},
|
||||
fetchSignature(id) {
|
||||
return this.findOneFromDef('signature', [id]);
|
||||
},
|
||||
fetchTaxes(id) {
|
||||
return this.findOneFromDef(`taxes`, [id]);
|
||||
},
|
||||
fetchSales(id) {
|
||||
return this.rawSqlFromDef('sales', [id]);
|
||||
},
|
||||
fetchPackagings(id) {
|
||||
return this.rawSqlFromDef('packagings', [id]);
|
||||
},
|
||||
fetchServices(id) {
|
||||
return this.rawSqlFromDef('services', [id]);
|
||||
},
|
||||
|
||||
getSubTotal() {
|
||||
let subTotal = 0.00;
|
||||
this.sales.forEach(sale => {
|
||||
subTotal += sale.quantity * sale.price * (1 - sale.discount / 100);
|
||||
});
|
||||
|
||||
return subTotal;
|
||||
},
|
||||
getTotalBase() {
|
||||
let totalBase = 0.00;
|
||||
this.taxes.forEach(tax => {
|
||||
totalBase += parseFloat(tax.Base);
|
||||
});
|
||||
|
||||
return totalBase;
|
||||
},
|
||||
getTotalTax() {
|
||||
let totalTax = 0.00;
|
||||
this.taxes.forEach(tax => {
|
||||
totalTax += parseFloat(tax.tax);
|
||||
});
|
||||
|
||||
return totalTax;
|
||||
},
|
||||
getTotal() {
|
||||
return this.getTotalBase() + this.getTotalTax();
|
||||
},
|
||||
getBotanical() {
|
||||
let phytosanitary = [];
|
||||
this.sales.forEach(sale => {
|
||||
if (sale.botanical)
|
||||
phytosanitary.push(sale.botanical);
|
||||
});
|
||||
|
||||
return phytosanitary.filter((item, index) =>
|
||||
phytosanitary.indexOf(item) == index
|
||||
).join(', ');
|
||||
}
|
||||
},
|
||||
const controller = {
|
||||
components: {
|
||||
'report-body': reportBody.build(),
|
||||
'report-header': reportHeader.build(),
|
||||
'report-footer': reportFooter.build()
|
||||
reportHeader: reportHeader,
|
||||
reportBody: reportBody,
|
||||
},
|
||||
props: {
|
||||
id: {
|
||||
|
@ -140,5 +27,306 @@ module.exports = {
|
|||
type: String,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const db = useDatabase();
|
||||
|
||||
onServerPrefetch(async() => {
|
||||
await fetchClient();
|
||||
await fetchTicket();
|
||||
await fetchAddress();
|
||||
await fetchSales();
|
||||
});
|
||||
|
||||
const deliverNoteType = props.type ? props.type : 'deliveryNote';
|
||||
const showPrices = deliverNoteType != 'withoutPrices';
|
||||
const hasObservations = computed(() => {
|
||||
return ticket.value.description !== null;
|
||||
});
|
||||
// footerType() {
|
||||
// const translatedType = this.$t(this.deliverNoteType);
|
||||
// return `${translatedType} ${this.id}`;
|
||||
// },
|
||||
|
||||
const client = ref();
|
||||
async function fetchClient() {
|
||||
client.value = await db.findOne(`
|
||||
SELECT
|
||||
c.id,
|
||||
c.socialName,
|
||||
c.street,
|
||||
c.fi
|
||||
FROM ticket t
|
||||
JOIN client c ON c.id = t.clientFk
|
||||
WHERE t.id = ?
|
||||
`, [props.id]);
|
||||
}
|
||||
|
||||
const ticket = ref();
|
||||
async function fetchTicket() {
|
||||
ticket.value = await db.findOne(
|
||||
`SELECT
|
||||
t.id,
|
||||
t.shipped,
|
||||
c.code companyCode,
|
||||
t.packages,
|
||||
tto.description
|
||||
FROM ticket t
|
||||
JOIN company c ON c.id = t.companyFk
|
||||
LEFT JOIN ticketObservation tto
|
||||
ON tto.ticketFk = t.id
|
||||
AND tto.observationTypeFk = (SELECT id FROM observationType WHERE code = 'deliveryNote')
|
||||
WHERE t.id = ?
|
||||
`, [props.id]);
|
||||
}
|
||||
|
||||
const address = ref();
|
||||
async function fetchAddress() {
|
||||
address.value = await db.findOne(
|
||||
`
|
||||
SELECT
|
||||
a.nickname,
|
||||
a.street,
|
||||
a.postalCode,
|
||||
a.city,
|
||||
p.name province
|
||||
FROM ticket t
|
||||
JOIN address a ON a.clientFk = t.clientFk
|
||||
AND a.id = t.addressFk
|
||||
LEFT JOIN province p ON p.id = a.provinceFk
|
||||
WHERE t.id = ?
|
||||
`, [props.id]);
|
||||
}
|
||||
|
||||
const sales = ref();
|
||||
async function fetchSales() {
|
||||
sales.value = await db.rawSql(
|
||||
`
|
||||
SELECT
|
||||
s.id,
|
||||
s.itemFk,
|
||||
s.concept,
|
||||
s.quantity,
|
||||
s.price,
|
||||
s.price - SUM(IF(ctr.id = 6, sc.value, 0)) netPrice,
|
||||
s.discount,
|
||||
i.size,
|
||||
i.stems,
|
||||
i.category,
|
||||
it.id itemTypeId,
|
||||
o.code AS origin,
|
||||
i.inkFk,
|
||||
s.ticketFk,
|
||||
tcl.code vatType,
|
||||
ib.ediBotanic botanical,
|
||||
i.tag5,
|
||||
i.value5,
|
||||
i.tag6,
|
||||
i.value6,
|
||||
i.tag7,
|
||||
i.value7
|
||||
FROM vn.sale s
|
||||
LEFT JOIN saleComponent sc ON sc.saleFk = s.id
|
||||
LEFT JOIN component cr ON cr.id = sc.componentFk
|
||||
LEFT JOIN componentType ctr ON ctr.id = cr.typeFk
|
||||
LEFT JOIN item i ON i.id = s.itemFk
|
||||
LEFT JOIN ticket t ON t.id = s.ticketFk
|
||||
LEFT JOIN origin o ON o.id = i.originFk
|
||||
LEFT JOIN country c ON c.id = o.countryFk
|
||||
LEFT JOIN supplier sp ON sp.id = t.companyFk
|
||||
LEFT JOIN itemType it ON it.id = i.typeFk
|
||||
LEFT JOIN itemCategory ic ON ic.id = it.categoryFk
|
||||
LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id
|
||||
AND itc.countryFk = sp.countryFk
|
||||
LEFT JOIN taxClass tcl ON tcl.id = itc.taxClassFk
|
||||
LEFT JOIN itemBotanicalWithGenus ib ON ib.itemFk = i.id
|
||||
AND ic.code = 'plant'
|
||||
AND ib.ediBotanic IS NOT NULL
|
||||
WHERE s.ticketFk = ?
|
||||
GROUP BY s.id
|
||||
ORDER BY (it.isPackaging), s.concept, s.itemFk
|
||||
`, [props.id]);
|
||||
}
|
||||
|
||||
function getSubTotal() {
|
||||
let subTotal = 0.00;
|
||||
for (const sale of sales.value)
|
||||
subTotal += sale.quantity * sale.price * (1 - sale.discount / 100);
|
||||
|
||||
return subTotal;
|
||||
}
|
||||
// getTotalBase() {
|
||||
// let totalBase = 0.00;
|
||||
// this.taxes.forEach(tax => {
|
||||
// totalBase += parseFloat(tax.Base);
|
||||
// });
|
||||
|
||||
// return totalBase;
|
||||
// },
|
||||
// getTotalTax() {
|
||||
// let totalTax = 0.00;
|
||||
// this.taxes.forEach(tax => {
|
||||
// totalTax += parseFloat(tax.tax);
|
||||
// });
|
||||
|
||||
// return totalTax;
|
||||
// },
|
||||
// getTotal() {
|
||||
// return this.getTotalBase() + this.getTotalTax();
|
||||
// },
|
||||
|
||||
return {
|
||||
props,
|
||||
toDate,
|
||||
toCurrency,
|
||||
deliverNoteType,
|
||||
client,
|
||||
ticket,
|
||||
address,
|
||||
sales,
|
||||
showPrices,
|
||||
hasObservations,
|
||||
getSubTotal
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = controller;
|
||||
|
||||
// module.exports = {
|
||||
// name: 'delivery-note',
|
||||
// async serverPrefetch() {
|
||||
// this.client = await this.fetchClient(this.id);
|
||||
// this.ticket = await this.fetchTicket(this.id);
|
||||
// this.sales = await this.fetchSales(this.id);
|
||||
// this.address = await this.fetchAddress(this.id);
|
||||
// this.services = await this.fetchServices(this.id);
|
||||
// this.taxes = await this.fetchTaxes(this.id);
|
||||
// this.packagings = await this.fetchPackagings(this.id);
|
||||
// this.signature = await this.fetchSignature(this.id);
|
||||
|
||||
// if (!this.ticket)
|
||||
// throw new Error('Something went wrong');
|
||||
// },
|
||||
// data() {
|
||||
// return {totalBalance: 0.00};
|
||||
// },
|
||||
// computed: {
|
||||
// dmsPath() {
|
||||
// if (!this.signature) return;
|
||||
|
||||
// const hash = md5(this.signature.id.toString()).substring(0, 3);
|
||||
// const file = `${config.storage.root}/${hash}/${this.signature.id}.png`;
|
||||
|
||||
// if (!fs.existsSync(file)) return null;
|
||||
|
||||
// const src = fs.readFileSync(file);
|
||||
// const base64 = Buffer.from(src, 'utf8').toString('base64');
|
||||
|
||||
// return `data:image/png;base64, ${base64}`;
|
||||
// },
|
||||
// deliverNoteType() {
|
||||
// return this.type ? this.type : 'deliveryNote';
|
||||
// },
|
||||
// serviceTotal() {
|
||||
// let total = 0.00;
|
||||
// this.services.forEach(service => {
|
||||
// total += parseFloat(service.price) * service.quantity;
|
||||
// });
|
||||
|
||||
// return total;
|
||||
// },
|
||||
// showPrices() {
|
||||
// return this.deliverNoteType != 'withoutPrices';
|
||||
// },
|
||||
// footerType() {
|
||||
// const translatedType = this.$t(this.deliverNoteType);
|
||||
// return `${translatedType} ${this.id}`;
|
||||
// },
|
||||
// hasObservations() {
|
||||
// return this.ticket.description !== null;
|
||||
// }
|
||||
|
||||
// },
|
||||
// methods: {
|
||||
// fetchClient(id) {
|
||||
// return this.findOneFromDef('client', [id]);
|
||||
// },
|
||||
// fetchTicket(id) {
|
||||
// return this.findOneFromDef('ticket', [id]);
|
||||
// },
|
||||
// fetchAddress(id) {
|
||||
// return this.findOneFromDef(`address`, [id]);
|
||||
// },
|
||||
// fetchSignature(id) {
|
||||
// return this.findOneFromDef('signature', [id]);
|
||||
// },
|
||||
// fetchTaxes(id) {
|
||||
// return this.findOneFromDef(`taxes`, [id]);
|
||||
// },
|
||||
// fetchSales(id) {
|
||||
// return this.rawSqlFromDef('sales', [id]);
|
||||
// },
|
||||
// fetchPackagings(id) {
|
||||
// return this.rawSqlFromDef('packagings', [id]);
|
||||
// },
|
||||
// fetchServices(id) {
|
||||
// return this.rawSqlFromDef('services', [id]);
|
||||
// },
|
||||
|
||||
// getSubTotal() {
|
||||
// let subTotal = 0.00;
|
||||
// this.sales.forEach(sale => {
|
||||
// subTotal += sale.quantity * sale.price * (1 - sale.discount / 100);
|
||||
// });
|
||||
|
||||
// return subTotal;
|
||||
// },
|
||||
// getTotalBase() {
|
||||
// let totalBase = 0.00;
|
||||
// this.taxes.forEach(tax => {
|
||||
// totalBase += parseFloat(tax.Base);
|
||||
// });
|
||||
|
||||
// return totalBase;
|
||||
// },
|
||||
// getTotalTax() {
|
||||
// let totalTax = 0.00;
|
||||
// this.taxes.forEach(tax => {
|
||||
// totalTax += parseFloat(tax.tax);
|
||||
// });
|
||||
|
||||
// return totalTax;
|
||||
// },
|
||||
// getTotal() {
|
||||
// return this.getTotalBase() + this.getTotalTax();
|
||||
// },
|
||||
// getBotanical() {
|
||||
// let phytosanitary = [];
|
||||
// this.sales.forEach(sale => {
|
||||
// if (sale.botanical)
|
||||
// phytosanitary.push(sale.botanical);
|
||||
// });
|
||||
|
||||
// return phytosanitary.filter((item, index) =>
|
||||
// phytosanitary.indexOf(item) == index
|
||||
// ).join(', ');
|
||||
// }
|
||||
// },
|
||||
// components: {
|
||||
// 'template-body': templateBody.build(),
|
||||
// 'report-header': reportHeader.build(),
|
||||
// 'report-footer': reportFooter.build()
|
||||
// },
|
||||
// props: {
|
||||
// id: {
|
||||
// type: Number,
|
||||
// required: true,
|
||||
// description: 'The ticket id'
|
||||
// },
|
||||
// type: {
|
||||
// type: String,
|
||||
// required: false
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
|
Loading…
Reference in New Issue