updated delivery-note, fixed fallback locale

This commit is contained in:
Joan Sanchez 2019-02-11 10:06:26 +01:00
parent 1ea032eba8
commit 7365a1e001
25 changed files with 441 additions and 260 deletions

View File

@ -7,7 +7,7 @@ RUN apt-get update \
ca-certificates \ ca-certificates \
gnupg2 \ gnupg2 \
libfontconfig \ libfontconfig \
&& curl -sL https://deb.nodesource.com/setup_8.x | bash - \ && curl -sL https://deb.nodesource.com/setup_10.x | bash - \
&& apt-get install -y --no-install-recommends \ && apt-get install -y --no-install-recommends \
nodejs \ nodejs \
&& apt-get purge -y --auto-remove \ && apt-get purge -y --auto-remove \

View File

@ -51,6 +51,7 @@ function backWatch(done) {
nodemon({ nodemon({
exec: commands.join(' && '), exec: commands.join(' && '),
ext: 'js html css',
args: ['backOnly'], args: ['backOnly'],
watch: backSources, watch: backSources,
done: done done: done

View File

@ -155,3 +155,10 @@
</vn-confirm> </vn-confirm>
<vn-add-stowaway vn-id="addStowaway" card-reload="$ctrl.cardReload()" ticket="$ctrl.ticket"></vn-add-stowaway> <vn-add-stowaway vn-id="addStowaway" card-reload="$ctrl.cardReload()" ticket="$ctrl.ticket"></vn-add-stowaway>
<vn-remove-stowaway vn-id="removeStowaway" card-reload="$ctrl.cardReload()" ticket="$ctrl.ticket"></vn-remove-stowaway> <vn-remove-stowaway vn-id="removeStowaway" card-reload="$ctrl.cardReload()" ticket="$ctrl.ticket"></vn-remove-stowaway>
<vn-confirm
vn-id="confirm-dialog"
on-response="$ctrl.returnDialog(response)"
question="Pickup order"
message="Do you want to send it directly?">
<tpl-buttons>asd</tpl-buttons>
</vn-confirm>

View File

@ -9,9 +9,10 @@ class Controller {
this.$translate = $translate; this.$translate = $translate;
this.moreOptions = [ this.moreOptions = [
{callback: this.showAddTurnDialog, name: 'Add turn', show: true}, {callback: this.showAddTurnDialog, name: 'Add turn', show: true},
{callback: this.showDeleteTicketDialog, name: 'Delete ticket', show: true},
{callback: this.showAddStowaway, name: 'Add stowaway', show: () => this.isTicketModule()}, {callback: this.showAddStowaway, name: 'Add stowaway', show: () => this.isTicketModule()},
{callback: this.showRemoveStowaway, name: 'Remove stowaway', show: () => this.shouldShowRemoveStowaway()}, {callback: this.showRemoveStowaway, name: 'Remove stowaway', show: () => this.shouldShowRemoveStowaway()},
{callback: this.showDeliveryNote, name: 'Show Delivery Note', show: true},
{callback: this.showDeleteTicketDialog, name: 'Delete ticket', show: true},
/* callback: this.showChangeShipped, name: 'Change shipped hour', show: true} */ /* callback: this.showChangeShipped, name: 'Change shipped hour', show: true} */
]; ];
} }
@ -157,6 +158,11 @@ class Controller {
get quicklinks() { get quicklinks() {
return this._quicklinks; return this._quicklinks;
} }
showDeliveryNote() {
let url = `/api/report/rpt-delivery-note?ticketFk=${this.ticket.id}`;
window.open(url);
}
} }
Controller.$inject = ['$state', '$scope', '$http', 'vnApp', '$translate']; Controller.$inject = ['$state', '$scope', '$http', 'vnApp', '$translate'];

View File

@ -1,6 +1,6 @@
import './index.js'; import './index.js';
xdescribe('Item Component vnTicketDescriptor', () => { describe('Item Component vnTicketDescriptor', () => {
let $httpBackend; let $httpBackend;
let controller; let controller;
@ -69,5 +69,15 @@ xdescribe('Item Component vnTicketDescriptor', () => {
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Ticket deleted'); expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Ticket deleted');
}); });
}); });
fdescribe('showDeliveryNote()', () => {
it('should open a new window showing a delivery note PDF document', () => {
let expectedPath = '/api/report/rpt-delivery-note?ticketFk=2';
spyOn(window, 'open');
controller.showDeliveryNote();
expect(window.open).toHaveBeenCalledWith(expectedPath);
});
});
}); });

View File

@ -7,3 +7,4 @@ Stowaways of the ticket: Polizones del ticket
Add stowaway: Añadir polizón Add stowaway: Añadir polizón
Remove stowaway: Borrar polizón Remove stowaway: Borrar polizón
Are you sure you want to delete this stowaway?: ¿Estas seguro de que quieres borrar este polizón? Are you sure you want to delete this stowaway?: ¿Estas seguro de que quieres borrar este polizón?
Show Delivery Note: Ver albarán

View File

@ -38,93 +38,26 @@
clear: both clear: both
} }
.row {
margin-bottom: 15px;
overflow: hidden;
display: block;
clear: both;
width: 100%
}
.row.small {
margin-bottom: 5px
}
.row .text {
margin-bottom: 5px
}
.row .control {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box
}
.row:last-child {
margin-bottom: 0
}
.row.inline .text {
display: table-cell;
margin-bottom: 0;
width: 30%
}
.row.inline .control {
display: table-cell;
padding-left: 20px;
font-weight: bold;
color: #000;
width: 70%
}
.row.inline .description {
position: static;
overflow: visible
}
.row .description {
position: relative;
padding-top: 2px;
font-size: 9px;
overflow: hidden;
display: block;
clear: both
}
.row .line {
border-bottom: 1px solid #DDD;
border-right: 1px solid #DDD;
border-left: 1px solid #DDD;
margin-top: 10px;
color: #999;
padding: 5px
}
.row .description span {
background-color: #FFF;
margin: -5px 0 0 50px;
display: block;
padding: 5px;
float: left
}
.panel { .panel {
position: relative position: relative;
margin-bottom: 20px;
padding-top: 10px;
break-inside: avoid;
break-before: always;
break-after: always;
} }
.panel .header { .panel .header {
background-color: #FFF; background-color: #FFF;
padding: 2.5px 5px; padding: 2.5px 10px;
position: absolute; position: absolute;
font-weight: bold; font-weight: bold;
top: 0px;
left: 17.5px; left: 17.5px;
top: -12px
} }
.panel .body { .panel .body {
border: 1px solid #CCC; border: 1px solid #CCC;
margin-top: 10px;
overflow: hidden; overflow: hidden;
padding: 20px padding: 20px
} }
@ -133,6 +66,16 @@
margin-top: 0 margin-top: 0
} }
.panel.dark .header {
border: 1px solid #808080;
background-color: #FFF;
}
.panel.dark .body {
border: 1px solid #808080;
background-color: #c0c0c0
}
.field { .field {
border-bottom: 1px solid #CCC; border-bottom: 1px solid #CCC;
border-left: 1px solid #CCC; border-left: 1px solid #CCC;
@ -157,11 +100,11 @@
} }
.pull-left { .pull-left {
float: left float: left !important
} }
.pull-right { .pull-right {
float: right float: right !important
} }
.vertical-text { .vertical-text {
@ -186,58 +129,38 @@ table {
width: 100% width: 100%
} }
.row-oriented .description,
.column-oriented .description {
font-size: 0.6em;
color: #888;
padding: 0 !important
}
.row-oriented .description .line,
.column-oriented .description .line {
border-bottom: 1px solid #DDD;
border-right: 1px solid #DDD;
border-left: 1px solid #DDD;
margin-top: 10px;
color: #999;
padding: 5px
}
.row-oriented .description span,
.column-oriented .description span {
background-color: #FFF;
margin: -5px 0 0 50px;
display: block;
padding: 5px;
float: left
}
.column-oriented { .column-oriented {
margin: 20px 0 margin: 20px 0
} }
.column-oriented tfoot { .column-oriented td,
border-top: 1px solid #808080; .column-oriented th {
}
.column-oriented td, .column-oriented th {
padding: 5px 10px padding: 5px 10px
} }
.column-oriented thead { .column-oriented thead {
background-color: #c0c0c0 background-color: #e5e5e5
} }
.column-oriented thead tr { .column-oriented thead tr {
border-bottom: 1px solid #808080; border-bottom: 1px solid #808080;
border-top: 1px solid #808080; border-top: 1px solid #808080;
background-color: #c0c0c0 background-color: #e5e5e5
}
.column-oriented tfoot {
border-top: 2px solid #808080;
} }
.column-oriented tfoot tr:first-child td { .column-oriented tfoot tr:first-child td {
padding-top: 20px !important; padding-top: 20px !important;
} }
.column-oriented .description {
border-bottom: 1px solid #DDD;
font-size: 0.8em
}
.panel .row-oriented td, .panel .row-oriented th { .panel .row-oriented td, .panel .row-oriented th {
padding: 10px 0 padding: 10px 0
} }
@ -250,3 +173,27 @@ table {
padding-left: 30px; padding-left: 30px;
width: 70% width: 70%
} }
.row-oriented .description {
padding: 0 !important;
font-size: 0.6em;
color: #888
}
.line {
border-bottom: 1px solid #DDD;
border-right: 1px solid #DDD;
border-left: 1px solid #DDD;
margin-top: 10px;
color: #999;
padding: 5px
}
.line span {
background-color: #FFF;
margin: -5px 0 0 50px;
display: block;
padding: 5px;
float: left
}

View File

@ -25,3 +25,7 @@
.font.small { .font.small {
font-size: 0.65em font-size: 0.65em
} }
.font.bold {
font-weight: bold
}

View File

View File

@ -26,7 +26,7 @@ module.exports = {
const result = await this.preFetch(component, ctx); const result = await this.preFetch(component, ctx);
const i18n = new VueI18n({ const i18n = new VueI18n({
locale: 'es', locale: 'es',
fallbackLocale: 'en' fallbackLocale: 'es'
}); });
const app = new Vue({i18n, const app = new Vue({i18n,
render: h => h(result.component)}); render: h => h(result.component)});
@ -106,9 +106,6 @@ module.exports = {
const options = { const options = {
format: 'A4', format: 'A4',
border: '1.5cm', border: '1.5cm',
header: {
height: '80px',
},
footer: { footer: {
height: '60px', height: '60px',
} }

View File

@ -1,5 +1,5 @@
footer { footer {
font-family: verdana, sans-serif; font-family: "Roboto", "Helvetica", "Arial", sans-serif;
font-size: 0.55em; font-size: 0.55em;
color: #555; color: #555;
zoom: 0.65 zoom: 0.65
@ -9,6 +9,10 @@ footer, footer p {
text-align: center text-align: center
} }
p.privacy {
font-size: 0.8em
}
footer .page { footer .page {
border-bottom: 2px solid #CCC; border-bottom: 2px solid #CCC;
padding-bottom: 2px padding-bottom: 2px

View File

@ -5,5 +5,5 @@
<section class="number">{{$t('numPages')}}</section> <section class="number">{{$t('numPages')}}</section>
</section> </section>
<p class="phytosanitary">{{$t('law.phytosanitary')}}</p> <p class="phytosanitary">{{$t('law.phytosanitary')}}</p>
<p v-html="$t('law.privacy')"></p> <p class="privacy" v-html="$t('law.privacy')"></p>
</footer> </footer>

View File

@ -7,8 +7,7 @@ module.exports = {
privacy: `En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal, privacy: `En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal,
le comunicamos que los datos personales que facilite se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L., le comunicamos que los datos personales que facilite se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L.,
pudiendo en todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, comunicándolo pudiendo en todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, comunicándolo
por escrito al domicilio social de la entidad. <br/> por escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación.`,
La finalidad del fichero es la gestión administrativa, contabilidad, y facturación.`,
} }
}, },
}, },

View File

@ -2,10 +2,10 @@ header {
font-family: "Roboto", "Helvetica", "Arial", sans-serif; font-family: "Roboto", "Helvetica", "Arial", sans-serif;
border-bottom: 1px solid #DDD; border-bottom: 1px solid #DDD;
padding-bottom: 10px; padding-bottom: 10px;
margin-bottom: 20px;
text-align: center; text-align: center;
font-size: 0.60em; font-size: 0.55em;
color: #555; color: #555
zoom: 0.65
} }
header img { header img {

View File

@ -1,5 +1,5 @@
<header> <header>
<img :src="embeded['/assets/images/report-logo.svg']" alt="Verdnatura"/> <img :src="embeded['/assets/images/report-logo.svg']" alt="Verdnatura"/>
<section>{{$t('company.registry')}}</section>
<section>{{$t('company.fiscalAddress')}}</section> <section>{{$t('company.fiscalAddress')}}</section>
<section>{{$t('company.registry')}}</section>
</header> </header>

View File

@ -3,9 +3,7 @@
<body> <body>
<section class="container"> <section class="container">
<!-- Header component --> <!-- Header component -->
<report-header id="pageHeader-first" <report-header :locale="locale"></report-header>
:locale="locale">
</report-header>
<!-- End header component --> <!-- End header component -->
<section class="main"> <section class="main">
<section class="columns"> <section class="columns">
@ -53,22 +51,23 @@
<thead> <thead>
<tr> <tr>
<th>{{$t('reference')}}</th> <th>{{$t('reference')}}</th>
<th>{{$t('quantity')}}</th> <th class="number">{{$t('quantity')}}</th>
<th>{{$t('claims')}}</th> <th class="number">{{$t('claims')}}</th>
<th>{{$t('concept')}}</th> <th>{{$t('concept')}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="sale in sales" :key="sale.id"> <tr v-for="sale in sales" :key="sale.id">
<td class="font gray">{{sale.id}}</td> <td class="font gray">{{sale.id}}</td>
<td>{{sale.quantity}}</td> <td class="number">{{sale.quantity}}</td>
<td>{{sale.claimQuantity}}</td> <td class="number">{{sale.claimQuantity}}</td>
<td>{{sale.concept}}</td> <td>{{sale.concept}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<section class="panel sign"> <section class="panel sign">
<section class="header">{{$t('clientSignature')}}</section>
<section class="body centered"> <section class="body centered">
<h3>{{clientName}}</h3> <h3>{{clientName}}</h3>
</section> </section>

View File

@ -10,6 +10,7 @@ module.exports = {
claims: 'Reclama', claims: 'Reclama',
reference: 'Referencia', reference: 'Referencia',
concept: 'Concepto', concept: 'Concepto',
clientSignature: 'Firma del cliente',
claim: 'Reclamación {0}', claim: 'Reclamación {0}',
sections: { sections: {
agency: { agency: {

View File

@ -1,3 +1,22 @@
table.column-oriented { #signature {
margin-top: 50px !important margin-top: 80px
}
#signature img {
margin-bottom: 20px;
width: 150px
}
#packagings {
box-sizing: border-box;
padding-right: 10px
}
#taxes {
box-sizing: border-box;
padding-left: 10px
}
.description.phytosanitary {
background-color: #e5e5e5
} }

View File

@ -1,13 +1,11 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="es"> <html lang="es">
<body> <body>
<section class="container" id="report"> <section class="container">
<!-- Header component --> <!-- Header component -->
<report-header id="pageHeader-first" <report-header :locale="ticket.locale"></report-header>
:locale="locale">
</report-header>
<!-- End header component --> <!-- End header component -->
<section class="main"> <section class="main" style="margin-bottom:100px">
<section class="columns"> <section class="columns">
<section class="size50"> <section class="size50">
<section class="size75"> <section class="size75">
@ -16,15 +14,15 @@
<tbody> <tbody>
<tr> <tr>
<td class="font gray uppercase">{{$t('clientId')}}</td> <td class="font gray uppercase">{{$t('clientId')}}</td>
<th>{{clientId}}</th> <th>{{client.id}}</th>
</tr> </tr>
<tr> <tr>
<td class="font gray uppercase">{{$t('ticketId')}}</td> <td class="font gray uppercase">{{$t('ticketId')}}</td>
<th>{{ticketId}}</th> <th>{{ticket.id}}</th>
</tr> </tr>
<tr> <tr>
<td class="font gray uppercase">{{$t('date')}}</td> <td class="font gray uppercase">{{$t('date')}}</td>
<th>{{dated()}}</th> <th>{{shipped}}</th>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -32,70 +30,165 @@
</section> </section>
<section class="size50"> <section class="size50">
<section class="panel"> <section class="panel">
<section class="header">{{$t('clientData')}}</section> <section class="header">{{$t('deliveryAddress')}}</section>
<section class="body"> <section class="body">
<h3 class="uppercase">{{clientName}}</h3> <h3 class="uppercase">{{address.nickname}}</h3>
<section> <section>
{{street}} {{address.street}}
</section> </section>
<section> <section>
{{postcode}}, {{city}} ({{province}}) {{address.postalCode}}, {{address.city}} ({{address.province}})
</section>
<section>
{{country}}
</section>
</section>
</section> </section>
</section> </section>
</section> </section>
<section class="panel">
<section class="header">{{$t('fiscalData')}}</section>
<section class="body">
<section>
{{client.socialName}}
</section>
<section>
{{client.street}}
</section>
<section>
{{client.fi}}
</section>
</section>
</section>
</section>
</section>
<table class="column-oriented"> <table class="column-oriented">
<thead> <thead>
<tr> <tr>
<th>{{$t('reference')}}</th> <td>{{$t('reference')}}</td>
<th>{{$t('quantity')}}</th> <td class="number">{{$t('quantity')}}</td>
<th>{{$t('concept')}}</th> <td>{{$t('concept')}}</td>
<th class="number">{{$t('size')}}</th> <td class="number">{{$t('price')}}</td>
<th>{{$t('cat')}}</th> <td class="centered">{{$t('discount')}}</td>
<th>{{$t('col')}}</th> <td class="centered">{{$t('vat')}}</td>
<th>{{$t('VAT')}}</th> <td class="number">{{$t('amount')}}</td>
<th>{{$t('price')}}</th>
<th>{{$t('%')}}</th>
<th>{{$t('amount')}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr v-for="sale in sales" :key="sale.id"> <template v-for="sale in sales">
<td>{{sale.ref</td> <tr class="font bold" :key="sale.id">
<td>{{sale}}</td> <td>{{sale.itemFk}}</td>
<td class="number">{{sale}}</td> <td class="number">{{sale.quantity}}</td>
<td class="number">{{sale}}</td> <td>{{sale.concept}}</td>
<td class="number">{{a}}</td> <td class="number">{{sale.price | currency('EUR')}}</td>
<td class="centered">{{sale.discount | percent}}</td>
<td class="centered">{{sale.vatType}}</td>
<td class="number">{{sale.price * sale.quantity * (1 - sale.discount / 100) | currency('EUR')}}</td>
</tr>
<tr class="description">
<td colspan="2" class="centered">
<strong class="font gray" v-if="sale.val1">{{sale.tag1}}</strong>
<span>{{sale.val1}}</span>
</td>
<td colspan="3" class="centered">
<strong class="font gray" v-if="sale.val2">{{sale.tag2}}</strong>
<span>{{sale.val2}}</span>
</td>
<td colspan="2" class="centered">
<strong class="font gray" v-if="sale.val3">{{sale.tag3}}</strong>
<span>{{sale.val3}}</span>
</td>
</tr>
<tr class="description phytosanitary" v-if="sale.passportNumber">
<td colspan="7">
{{sale.ediBotanic}} {{sale.denomination}} {{sale.countryCode}}-{{sale.passportNumber}}
<span v-if="sale.isProtectedZone">ZP</span>
</td>
</tr>
</template>
<!-- FIXME - APPLY CSS POST-RENDER -->
<tr >
<td colspan="7"></td>
</tr> </tr>
</tbody> </tbody>
<tfoot> <tfoot>
<!-- <tr> <tr>
<td></td> <td colspan="6">
<td></td> <span class="pull-right">{{$t('subtotal')}}</span>
<td class="number"><strong class="pull-left">Total</strong> {{getTotalDebtOut()}}</td> </td>
<td class="number">{{getTotalDebtIn()}}</td> <td class="number">{{getSubTotal() | currency('EUR')}}</td>
<td class="number">{{totalBalance}}</td> </tr>
</tr> -->
</tfoot> </tfoot>
</table> </table>
<section class="columns">
<div class="panel" style="text-align:center;background-color:red"> <section id="packagings" class="size50 pull-left" v-if="packagings.length > 0">
<div class="header">Firma digital</div> <h3>{{$t('packaging')}}</h3>
<img width="200" src="http://windows.verdnatura.es/signatures/tickets/1161229.png"/> <table class="column-oriented">
<section>{{dmsCreated}}</section> <thead>
</div> <tr>
</div> <td>Id</td>
<td>{{$t('concept')}}</td>
<td class="number">{{$t('quantity')}}</td>
</tr>
</thead>
<tbody>
<tr v-for="packaging in packagings">
<td>{{packaging.itemFk}}</td>
<td>{{packaging.name}}</td>
<td class="number">{{packaging.quantity}}</td>
</tr>
</tbody>
<tfoot>
<tr class="font bold">
<td colspan="2">{{$t('total')}}</td>
<td class="number">0</td>
</tr>
</tfoot>
</table>
</section>
<section id="taxes" class="size50 pull-right" v-if="taxes">
<h3>{{$t('taxBreakdown')}}</h3>
<table class="column-oriented">
<thead>
<tr>
<td>{{$t('type')}}</td>
<td class="number">{{$t('taxBase')}}</td>
<td>{{$t('tax')}}</td>
<td class="number">{{$t('fee')}}</td>
</tr>
</thead>
<tbody>
<tr v-for="tax in taxes">
<td>{{tax.name}}</td>
<td class="number">{{tax.Base | currency('EUR')}}</td>
<td>{{tax.vatPercent | percent}}</td>
<td class="number">{{tax.tax | currency('EUR')}}</td>
</tr>
</tbody>
<tfoot>
<tr class="font bold">
<td>{{$t('subtotal')}}</td>
<td class="number">{{getTotalBase() | currency('EUR')}}</td>
<td></td>
<td class="number">{{getTotalTax()| currency('EUR')}}</td>
</tr>
<tr class="font bold">
<td colspan="2">{{$t('total')}}</td>
<td colspan="2" class="number">{{getTotal() | currency('EUR')}}</td>
</tr>
</tfoot>
</table>
</section>
</section>
<section id="signature" class="panel dark" v-if="signature && signature.id">
<section class="header">Firma digital</section>
<section class="body centered">
<img v-bind:src="dmsPath"/>
<section>{{signature.created | date}}</section>
</section>
</section>
</section> </section>
<!-- Footer component --> <!-- Footer component -->
<report-footer id="pageFooter" <report-footer id="pageFooter"
:left-text="$t('ticket', [ticketId])" :left-text="$t('ticket', [ticket.id])"
:center-text="clientName" :center-text="client.socialName"
:locale="locale"> :locale="client.locale">
</report-footer> </report-footer>
<!-- End footer component --> <!-- End footer component -->
</section> </section>

View File

@ -5,65 +5,94 @@ const UserException = require(`${appPath}/lib/exceptions/userException`);
module.exports = { module.exports = {
name: 'rpt-delivery-note', name: 'rpt-delivery-note',
async asyncData(ctx, params) { async asyncData(ctx, params) {
const promises = []; Object.assign(this, this.methods);
const data = {};
if (!params.ticketFk) const [[client]] = await this.fetchClient(params.ticketFk);
throw new UserException('No ticket id specified'); const [[ticket]] = await this.fetchTicket(params.ticketFk);
const [[address]] = await this.fetchAddress(params.ticketFk);
const [[signature]] = await this.fetchSignature(params.ticketFk);
const [[taxes]] = await this.fetchTaxes(params.ticketFk);
const [sales] = await this.fetchSales(params.ticketFk);
const [packagings] = await this.fetchPackagings(params.ticketFk);
promises.push(this.methods.fetchClient(params.ticketFk)); if (!ticket)
promises.push(this.methods.fetchSales(params.ticketFk)); throw new UserException('No ticket data found');
return Promise.all(promises).then(result => { return {client, ticket, address, sales, taxes, packagings, signature};
const [[client]] = result[0];
const [sales] = result[1];
if (!client)
throw new UserException('No client data found');
Object.assign(data, client, {sales});
return data;
});
}, },
created() { created() {
if (this.locale) if (this.client.locale)
this.$i18n.locale = this.locale; this.$i18n.locale = this.client.locale;
}, },
data() { data() {
return {totalBalance: 0.00}; return {totalBalance: 0.00};
}, },
computed: { computed: {
dmsPath() { dmsPath() {
return `http://windows.verdnatura.es/signatures/tickets/1161229.png`; const hostPath = 'http://windows.verdnatura.es/signatures/tickets';
if (this.signature && this.signature.id)
return `${hostPath}/${this.signature.id}.png`;
},
shipped() {
return strftime('%d-%m-%Y', this.ticket.shipped);
}
},
filters: {
currency(input, currency = 'EUR') {
return new Intl.NumberFormat('es', {
style: 'currency', currency
}).format(parseFloat(input));
},
percent(input) {
return new Intl.NumberFormat('es', {
style: 'percent',
minimumFractionDigits: 0,
maximumFractionDigits: 0
}).format(parseFloat(input));
},
date(input) {
return strftime('%d-%m-%Y', input);
} }
}, },
methods: { methods: {
fetchClient(ticketFk) { fetchClient(ticketFk) {
return database.pool.query( return database.pool.query(
`SELECT `SELECT
c.id clientId, c.id,
t.id ticketId,
u.lang locale,
c.email AS recipient, c.email AS recipient,
c.socialName AS clientName, c.socialName,
c.street, c.street,
c.postcode,
c.city,
c.fi, c.fi,
p.name AS province, u.lang locale
ct.country,
dt.dmsFk,
d.created AS dmsCreated
FROM ticket t FROM ticket t
JOIN client c ON c.id = t.clientFk JOIN client c ON c.id = t.clientFk
JOIN account.user u ON u.id = c.id JOIN account.user u ON u.id = c.id
JOIN country ct ON ct.id = c.countryFk
LEFT JOIN province p ON p.id = c.provinceFk
LEFT JOIN dmsTicket dt ON dt.ticketFk = t.id
LEFT JOIN dms d ON d.id = dt.dmsFk
WHERE t.id = ?`, [ticketFk]); WHERE t.id = ?`, [ticketFk]);
}, },
fetchTicket(ticketFk) {
return database.pool.query(
`SELECT
t.id,
t.shipped
FROM ticket t
JOIN client c ON c.id = t.clientFk
JOIN account.user u ON u.id = c.id
WHERE t.id = ?`, [ticketFk]);
},
fetchAddress(ticketFk) {
return database.pool.query(
`SELECT
a.nickname,
a.street,
a.postalCode,
a.city,
p.name province
FROM ticket t
JOIN address a ON a.clientFk = t.clientFk
LEFT JOIN province p ON p.id = a.provinceFk
WHERE t.id = ?`, [ticketFk]);
},
fetchSales(ticketFk) { fetchSales(ticketFk) {
return database.pool.query( return database.pool.query(
`SELECT `SELECT
@ -78,45 +107,105 @@ module.exports = {
s.discount, s.discount,
i.size, i.size,
i.stems, i.stems,
ic.type taxType,
i.category, i.category,
it.id itemTypeId, it.id itemTypeId,
o.code AS origin, o.code AS origin,
i.inkFk, i.inkFk,
s.ticketFk, s.ticketFk,
tcl.code vatType,
ibwg.ediBotanic,
ppa.denomination,
pp.number passportNumber,
be.isProtectedZone,
c.code AS countryCode,
ita.tag1, ita.tag1,
ita.val1, ita.val1,
ita.tag2, ita.tag2,
ita.val2, ita.val2,
ita.tag3, ita.tag3,
ita.val3 ita.val3
FROM sale s FROM vn.sale s
LEFT JOIN saleComponent sc ON sc.saleFk = s.id LEFT JOIN saleComponent sc ON sc.saleFk = s.id
LEFT JOIN componentRate cr ON cr.id = sc.componentFk LEFT JOIN componentRate cr ON cr.id = sc.componentFk
LEFT JOIN componentTypeRate ctr ON ctr.id = cr.componentTypeRate LEFT JOIN componentTypeRate ctr ON ctr.id = cr.componentTypeRate
LEFT JOIN item i ON i.id = s.itemFk LEFT JOIN item i ON i.id = s.itemFk
LEFT JOIN ticket t ON t.id = s.ticketFk LEFT JOIN ticket t ON t.id = s.ticketFk
LEFT JOIN origin o ON o.id = i.originFk LEFT JOIN origin o ON o.id = i.originFk
INNER JOIN supplier sp ON sp.id = t.companyFk LEFT JOIN country c ON c.id = o.countryFk
INNER JOIN itemType it ON it.id = i.typeFk LEFT JOIN supplier sp ON sp.id = t.companyFk
LEFT JOIN LEFT JOIN itemType it ON it.id = i.typeFk
(SELECT * LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id
FROM AND itc.countryFk = sp.countryFk
(SELECT tt.countryFk, tcc.taxClassFk, tc.type LEFT JOIN taxClass tcl ON tcl.id = itc.taxClassFk
FROM taxClassCode tcc LEFT JOIN itemTagArranged ita ON ita.itemFk = s.itemFk
JOIN taxCode tc ON tc.id = tcc.taxCodeFk LEFT JOIN plantpassport pp ON pp.producerFk = i.producerFk
JOIN taxType tt ON tt.id = tc.taxTypeFk LEFT JOIN plantpassportAuthority ppa ON ppa.id = pp.plantpassportAuthorityFk
WHERE tcc.effectived <= '2019-01-29 13:00:00' LEFT JOIN itemBotanicalWithGenus ibwg ON ibwg.itemFk = i.id
ORDER BY tcc.effectived DESC) tx LEFT JOIN botanicExport be ON be.restriction = 'pasaporte fitosanitario'
GROUP BY tx.countryFk, tx.taxClassFk) ic ON ic.countryFk = sp.countryFk LEFT JOIN ediGenus eg ON eg.id = be.ediGenusFk
AND ic.taxClassFk = i.taxClassFk LEFT JOIN ediSpecie es ON es.id = be.ediSpecieFk
JOIN vn.itemTagArranged ita ON ita.itemFk = s.itemFk AND ibwg.ediBotanic LIKE CONCAT(
IFNULL(eg.latinGenusName, ''),
IF(es.latinSpeciesName > '',
CONCAT(' ', es.latinSpeciesName), ''),
'%')
WHERE s.ticketFk = ? WHERE s.ticketFk = ?
GROUP BY s.id GROUP BY s.id
ORDER BY (it.isPackaging), s.concept, s.itemFk`, [ticketFk]); ORDER BY (it.isPackaging), s.concept, s.itemFk`, [ticketFk]);
}, },
dated: () => { fetchTaxes(ticketFk) {
return strftime('%d-%m-%Y', new Date()); return database.pool.query(
`CALL vn.ticketGetTaxAdd(?)`, [ticketFk]);
},
fetchPackagings(ticketFk) {
return database.pool.query(
`SELECT
tp.quantity,
i.name,
p.itemFk
FROM ticketPackaging tp
JOIN packaging p ON p.id = tp.packagingFk
JOIN item i ON i.id = p.itemFk
WHERE tp.ticketFk = ?
ORDER BY itemFk`, [ticketFk]);
},
fetchSignature(ticketFk) {
return database.pool.query(
`SELECT
d.id,
d.created
FROM ticket t
JOIN dmsTicket dt ON dt.ticketFk = t.id
JOIN dms d ON d.id = dt.dmsFk
AND d.file LIKE '%.png'
WHERE t.id = ?`, [ticketFk]);
},
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();
}, },
}, },
components: { components: {

View File

@ -4,12 +4,24 @@ module.exports = {
title: 'Albarán', title: 'Albarán',
ticketId: 'Albarán', ticketId: 'Albarán',
clientId: 'Cliente', clientId: 'Cliente',
clientData: 'Datos del cliente', deliveryAddress: 'Dirección de entrega',
fiscalData: 'Datos fiscales',
date: 'Fecha', date: 'Fecha',
reference: 'Ref.',
quantity: 'Cant.',
concept: 'Concepto', concept: 'Concepto',
invoiced: 'Facturado', price: 'PVP/u',
payed: 'Pagado', discount: 'Dto.',
balance: 'Saldo', vat: 'IVA',
amount: 'Importe',
type: 'Tipo',
taxBase: 'Base imp.',
tax: 'Tasa',
fee: 'Cuota',
packaging: 'Cubos y embalajes',
taxBreakdown: 'Desglose impositivo',
total: 'Total',
subtotal: 'Subtotal',
ticket: 'Albarán {0}' ticket: 'Albarán {0}'
}, },
}, },

View File

@ -3,9 +3,7 @@
<body> <body>
<section class="container" id="report"> <section class="container" id="report">
<!-- Header component --> <!-- Header component -->
<report-header id="pageHeader-first" <report-header :locale="locale"></report-header>
:locale="locale">
</report-header>
<!-- End header component --> <!-- End header component -->
<section class="main"> <section class="main">
<!-- Report start --> <!-- Report start -->

View File

@ -3,9 +3,7 @@
<body> <body>
<section class="container"> <section class="container">
<!-- Header component --> <!-- Header component -->
<report-header id="pageHeader-first" <report-header :locale="locale"></report-header>
:locale="locale">
</report-header>
<!-- End header component --> <!-- End header component -->
<section class="main"> <section class="main">
<section class="columns"> <section class="columns">
@ -77,7 +75,7 @@
</section> </section>
<!-- Footer component --> <!-- Footer component -->
<report-footer id="pageFooter" <report-footer id="pageFooter"
:left-text="$t('claim', [claimId])" :left-text="$t('client', [clientId])"
:center-text="clientName" :center-text="clientName"
:locale="locale"> :locale="locale">
</report-footer> </report-footer>

View File

@ -3,9 +3,7 @@
<body> <body>
<section class="container"> <section class="container">
<!-- Header component --> <!-- Header component -->
<report-header id="pageHeader-first" <report-header :locale="locale"></report-header>
:locale="locale">
</report-header>
<!-- End header component --> <!-- End header component -->
<section class="main"> <section class="main">
<h1 class="title centered">{{$t('title')}}</h1> <h1 class="title centered">{{$t('title')}}</h1>
@ -145,7 +143,7 @@
</section> </section>
<!-- Footer component --> <!-- Footer component -->
<report-footer id="pageFooter" <report-footer id="pageFooter"
:left-text="$t('claim', [claimId])" :left-text="$t('order', [mandateCode])"
:center-text="clientName" :center-text="clientName"
:locale="locale"> :locale="locale">
</report-footer> </report-footer>

View File

@ -3,9 +3,7 @@
<body> <body>
<section class="container" id="report"> <section class="container" id="report">
<!-- Header component --> <!-- Header component -->
<report-header id="pageHeader-first" <report-header :locale="locale"></report-header>
:locale="locale">
</report-header>
<!-- End header component --> <!-- End header component -->
<section class="main"> <section class="main">
<!-- Report start --> <!-- Report start -->