2983 - Invoice tickets from ticket index #685
|
@ -3,7 +3,6 @@
|
|||
SCHEMAS=(
|
||||
account
|
||||
bs
|
||||
bi
|
||||
cache
|
||||
edi
|
||||
hedera
|
||||
|
|
|
@ -18,20 +18,15 @@
|
|||
"acquireTimeout": 20000
|
||||
},
|
||||
"osticket": {
|
||||
"connector": "vn-mysql",
|
||||
"database": "vn",
|
||||
"debug": false,
|
||||
"host": "localhost",
|
||||
"port": "3306",
|
||||
"username": "root",
|
||||
"password": "root"
|
||||
"connector": "memory",
|
||||
"timezone": "local"
|
||||
},
|
||||
"tempStorage": {
|
||||
"name": "tempStorage",
|
||||
"connector": "loopback-component-storage",
|
||||
"provider": "filesystem",
|
||||
"provider": "filesystem",
|
||||
"root": "./storage/tmp",
|
||||
"maxFileSize": "262144000",
|
||||
"maxFileSize": "262144000",
|
||||
"allowedContentTypes": [
|
||||
"application/x-7z-compressed",
|
||||
"application/x-zip-compressed",
|
||||
|
@ -41,17 +36,17 @@
|
|||
"application/zip",
|
||||
"application/rar",
|
||||
"multipart/x-zip",
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/jpg"
|
||||
]
|
||||
},
|
||||
"dmsStorage": {
|
||||
"name": "dmsStorage",
|
||||
"connector": "loopback-component-storage",
|
||||
"provider": "filesystem",
|
||||
"provider": "filesystem",
|
||||
"root": "./storage/dms",
|
||||
"maxFileSize": "262144000",
|
||||
"maxFileSize": "262144000",
|
||||
"allowedContentTypes": [
|
||||
"application/x-7z-compressed",
|
||||
"application/x-zip-compressed",
|
||||
|
@ -61,32 +56,32 @@
|
|||
"application/zip",
|
||||
"application/rar",
|
||||
"multipart/x-zip",
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/jpg"
|
||||
]
|
||||
},
|
||||
"imageStorage": {
|
||||
"name": "imageStorage",
|
||||
"connector": "loopback-component-storage",
|
||||
"provider": "filesystem",
|
||||
"provider": "filesystem",
|
||||
"root": "./storage/image",
|
||||
"maxFileSize": "52428800",
|
||||
"maxFileSize": "52428800",
|
||||
"allowedContentTypes": [
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/jpeg",
|
||||
"image/jpg"
|
||||
]
|
||||
},
|
||||
"invoiceStorage": {
|
||||
"name": "invoiceStorage",
|
||||
"connector": "loopback-component-storage",
|
||||
"provider": "filesystem",
|
||||
"provider": "filesystem",
|
||||
"root": "./storage/pdfs/invoice",
|
||||
"maxFileSize": "52428800",
|
||||
"maxFileSize": "52428800",
|
||||
"allowedContentTypes": [
|
||||
"application/octet-stream",
|
||||
"application/pdf"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,7 +60,8 @@
|
|||
<vn-horizontal>
|
||||
<vn-input-number
|
||||
ng-model="$ctrl.deliveredAmount"
|
||||
label="Delivered amount">
|
||||
label="Delivered amount"
|
||||
step="0.01">
|
||||
</vn-input-number>
|
||||
<vn-input-number
|
||||
disabled="true"
|
||||
|
|
|
@ -10,73 +10,73 @@ module.exports = Self => {
|
|||
accepts: [
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
type: 'object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'search',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
description: 'Searchs the invoiceOut by id',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'clientFk',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'The client id',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'fi',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
description: 'The client fiscal id',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'hasPdf',
|
||||
type: 'Boolean',
|
||||
type: 'boolean',
|
||||
description: 'Whether the the invoiceOut has PDF or not',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'amount',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The amount filter',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'min',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The minimun amount flter',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'max',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The maximun amount flter',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'issued',
|
||||
type: 'Date',
|
||||
type: 'date',
|
||||
description: 'The issued date filter',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'created',
|
||||
type: 'Date',
|
||||
type: 'date',
|
||||
description: 'The created date filter',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'dued',
|
||||
type: 'Date',
|
||||
type: 'date',
|
||||
description: 'The due date filter',
|
||||
http: {source: 'query'}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
|
|
|
@ -10,48 +10,57 @@ module.exports = Self => {
|
|||
accepts: [
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
type: 'object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'tags',
|
||||
type: ['Object'],
|
||||
type: ['object'],
|
||||
description: 'List of tags to filter with',
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'search',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
description: `If it's and integer searchs by id, otherwise it searchs by name`,
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'Item id',
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'categoryFk',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'Category id',
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'typeFk',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'Type id',
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'isActive',
|
||||
type: 'Boolean',
|
||||
type: 'boolean',
|
||||
description: 'Whether the the item is or not active',
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'salesPersonFk',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'The buyer of the item',
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'description',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
description: 'The item description',
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'stemMultiplier',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'The item multiplier',
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
|
@ -60,23 +69,28 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.filter = async(ctx, filter) => {
|
||||
let conn = Self.dataSource.connector;
|
||||
Self.filter = async(ctx, filter, options) => {
|
||||
const conn = Self.dataSource.connector;
|
||||
let myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
let codeWhere;
|
||||
|
||||
if (ctx.args.search) {
|
||||
let items = await Self.app.models.ItemBarcode.find({
|
||||
const items = await Self.app.models.ItemBarcode.find({
|
||||
where: {code: ctx.args.search},
|
||||
fields: ['itemFk']
|
||||
});
|
||||
let itemIds = [];
|
||||
}, myOptions);
|
||||
const itemIds = [];
|
||||
for (const item of items)
|
||||
itemIds.push(item.itemFk);
|
||||
|
||||
codeWhere = {'i.id': {inq: itemIds}};
|
||||
}
|
||||
|
||||
let where = buildFilter(ctx.args, (param, value) => {
|
||||
const where = buildFilter(ctx.args, (param, value) => {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return /^\d+$/.test(value)
|
||||
|
@ -90,8 +104,8 @@ module.exports = Self => {
|
|||
return {'i.stemMultiplier': value};
|
||||
case 'typeFk':
|
||||
return {'i.typeFk': value};
|
||||
case 'category':
|
||||
return {'ic.name': value};
|
||||
case 'categoryFk':
|
||||
return {'ic.id': value};
|
||||
case 'salesPersonFk':
|
||||
return {'it.workerFk': value};
|
||||
case 'origin':
|
||||
|
@ -104,7 +118,7 @@ module.exports = Self => {
|
|||
});
|
||||
filter = mergeFilters(filter, {where});
|
||||
|
||||
let stmts = [];
|
||||
const stmts = [];
|
||||
let stmt;
|
||||
|
||||
stmt = new ParameterizedSQL(
|
||||
|
@ -173,9 +187,10 @@ module.exports = Self => {
|
|||
stmt.merge(conn.makeWhere(filter.where));
|
||||
stmt.merge(conn.makePagination(filter));
|
||||
|
||||
let itemsIndex = stmts.push(stmt) - 1;
|
||||
let sql = ParameterizedSQL.join(stmts, ';');
|
||||
let result = await conn.executeStmt(sql);
|
||||
const itemsIndex = stmts.push(stmt) - 1;
|
||||
const sql = ParameterizedSQL.join(stmts, ';');
|
||||
const result = await conn.executeStmt(sql, myOptions);
|
||||
|
||||
return itemsIndex === 0 ? result : result[itemsIndex];
|
||||
};
|
||||
};
|
||||
|
|
|
@ -2,29 +2,62 @@ const app = require('vn-loopback/server/server');
|
|||
|
||||
describe('item filter()', () => {
|
||||
it('should return 1 result filtering by id', async() => {
|
||||
let filter = {};
|
||||
let result = await app.models.Item.filter({args: {filter: filter, search: 1}});
|
||||
const tx = await app.models.Item.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0].id).toEqual(1);
|
||||
try {
|
||||
const filter = {};
|
||||
const ctx = {args: {filter: filter, search: 1}};
|
||||
const result = await app.models.Item.filter(ctx, filter, options);
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0].id).toEqual(1);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return 1 result filtering by barcode', async() => {
|
||||
let filter = {};
|
||||
let result = await app.models.Item.filter({args: {filter: filter, search: 4444444444}});
|
||||
const tx = await app.models.Item.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0].id).toEqual(2);
|
||||
try {
|
||||
const filter = {};
|
||||
const ctx = {args: {filter: filter, search: 4444444444}};
|
||||
const result = await app.models.Item.filter(ctx, filter, options);
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0].id).toEqual(2);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return 2 results using filter and tags', async() => {
|
||||
let filter = {
|
||||
order: 'isActive ASC, name',
|
||||
limit: 8
|
||||
};
|
||||
let tags = [{value: 'medical box', tagFk: 58}];
|
||||
let result = await app.models.Item.filter({args: {filter: filter, typeFk: 5, tags: tags}});
|
||||
const tx = await app.models.Item.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
|
||||
expect(result.length).toEqual(2);
|
||||
try {
|
||||
const filter = {
|
||||
order: 'isActive ASC, name',
|
||||
limit: 8
|
||||
};
|
||||
const tags = [{value: 'medical box', tagFk: 58}];
|
||||
const ctx = {args: {filter: filter, typeFk: 5, tags: tags}};
|
||||
const result = await app.models.Item.filter(ctx, filter, options);
|
||||
|
||||
expect(result.length).toEqual(2);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -91,8 +91,10 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
getActiveContract() {
|
||||
this.$http.get(`Workers/${this.worker.id}/activeContract`)
|
||||
.then(res => this.businessId = res.data.businessFk);
|
||||
this.$http.get(`Workers/${this.worker.id}/activeContract`).then(res => {
|
||||
if (res.data)
|
||||
this.businessId = res.data.businessFk;
|
||||
});
|
||||
}
|
||||
|
||||
getContractHolidays() {
|
||||
|
|
|
@ -90,7 +90,10 @@ class Controller extends Section {
|
|||
|
||||
getActiveContract() {
|
||||
return this.$http.get(`Workers/${this.worker.id}/activeContract`)
|
||||
.then(res => this.businessId = res.data.businessFk);
|
||||
.then(res => {
|
||||
if (res.data)
|
||||
this.businessId = res.data.businessFk;
|
||||
});
|
||||
}
|
||||
|
||||
fetchHours() {
|
||||
|
@ -111,6 +114,8 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
getAbsences() {
|
||||
if (!this.businessId) return;
|
||||
|
||||
const fullYear = this.started.getFullYear();
|
||||
let params = {
|
||||
businessFk: this.businessId,
|
||||
|
|
|
@ -1,163 +1,166 @@
|
|||
<!DOCTYPE html>
|
||||
<html v-bind:lang="$i18n.locale">
|
||||
<body>
|
||||
<table class="grid">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<!-- Header block -->
|
||||
<report-header v-bind="$props"></report-header>
|
||||
<!-- Block -->
|
||||
<div class="grid-row route-block" v-for="route in routes">
|
||||
<div class="grid-block">
|
||||
<h1 class="title uppercase">{{$t('route')}} {{route.id}}</h1>
|
||||
<div class="panel">
|
||||
<div class="header">{{$t('information')}}</div>
|
||||
<div class="body">
|
||||
<div>
|
||||
<table width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('route')}}</th>
|
||||
<td>{{route.id}}</td>
|
||||
<th class="font gray align-right">{{$t('driver')}}</th>
|
||||
<td>{{route.userNickName}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('date')}}</th>
|
||||
<td>{{route.created | date('%d-%m-%Y')}}</td>
|
||||
<th class="font gray align-right">{{$t('vehicle')}}</th>
|
||||
<td>{{route.vehicleTradeMark}} {{route.vehicleModel}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('time')}}</th>
|
||||
<td>{{route.time | date('%H:%M')}}</td>
|
||||
<td></td>
|
||||
<td>{{route.plateNumber}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('volume')}}</th>
|
||||
<td>{{route.m3}}</td>
|
||||
<th class="font gray align-right">{{$t('agency')}}</th>
|
||||
<td>{{route.agencyName}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="contained">
|
||||
<table class="middle centered" width="70%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<p class="small">Hora inicio</p>
|
||||
</td>
|
||||
<td>
|
||||
<p class="small">Hora fin</p>
|
||||
</td>
|
||||
<td class="gap"></td>
|
||||
<td>
|
||||
<p class="small">Km inicio</p>
|
||||
</td>
|
||||
<td>
|
||||
<p class="small">Km fin</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td v-for="i in 2">
|
||||
<div class="field rectangle">
|
||||
<span></span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="gap"></td>
|
||||
<td v-for="i in 2">
|
||||
<div class="field rectangle">
|
||||
<span></span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Route ticket list -->
|
||||
<div class="no-page-break" v-for="ticket in route.tickets">
|
||||
<div>
|
||||
<table class="column-oriented repeatable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="number">{{$t('order')}}</th>
|
||||
<th class="number">{{$t('ticket')}}</th>
|
||||
<th width="50%">{{$t('client')}}</th>
|
||||
<th class="number">{{$t('address')}}</th>
|
||||
<th class="number">{{$t('packages')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="number">{{ticket.priority}}</td>
|
||||
<td class="number">{{ticket.id}}</td>
|
||||
<td width="50%">{{ticket.clientFk}} {{ticket.addressName}}</td>
|
||||
<td v-if="ticket.addressFk" class="number">
|
||||
{{ticket.addressFk.toString().substr(0, ticket.addressFk.toString().length - 3)}}
|
||||
<span class="black-container">
|
||||
{{ticket.addressFk.toString().substr(-3, 3)}}
|
||||
</span>
|
||||
</td>
|
||||
<td class="number">{{ticket.packages}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<body>
|
||||
<table class="grid">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<!-- Header block -->
|
||||
<report-header v-bind="$props"></report-header>
|
||||
<!-- Block -->
|
||||
<div class="grid-row route-block" v-for="route in routes">
|
||||
<div class="grid-block">
|
||||
<h1 class="title uppercase">{{$t('route')}} {{route.id}}</h1>
|
||||
<div class="panel">
|
||||
<div class="header">{{$t('information')}}</div>
|
||||
<div class="body">
|
||||
<div>
|
||||
<table width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('street')}}</th>
|
||||
<td>{{ticket.street}}</td>
|
||||
<th class="font gray align-right">{{$t('postcode')}}</th>
|
||||
<td>{{ticket.postalCode}}</td>
|
||||
<th class="font gray align-right">{{$t('route')}}</th>
|
||||
<td>{{route.id}}</td>
|
||||
<th class="font gray align-right">{{$t('driver')}}</th>
|
||||
<td>{{route.userNickName}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('city')}}</th>
|
||||
<td>{{ticket.city}}</td>
|
||||
<th class="font gray align-right">{{$t('date')}}</th>
|
||||
<td>{{route.created | date('%d-%m-%Y')}}</td>
|
||||
<th class="font gray align-right">{{$t('vehicle')}}</th>
|
||||
<td>{{route.vehicleTradeMark}} {{route.vehicleModel}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('time')}}</th>
|
||||
<td>{{route.time | date('%H:%M')}}</td>
|
||||
<td></td>
|
||||
<td>{{route.plateNumber}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('volume')}}</th>
|
||||
<td>{{route.m3}}</td>
|
||||
<th class="font gray align-right">{{$t('agency')}}</th>
|
||||
<td>{{ticket.ticketAgency}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('mobile')}}</th>
|
||||
<td>{{ticket.mobile}}</td>
|
||||
<th class="font gray align-right">{{$t('phone')}}</th>
|
||||
<td>{{ticket.phone}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('warehouse')}}</th>
|
||||
<td>{{ticket.warehouseName}}</td>
|
||||
<th class="font gray align-right">{{$t('salesPerson')}}</th>
|
||||
<td>{{ticket.salesPersonName}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('import')}}</th>
|
||||
<td>{{ticket.import | currency('EUR', $i18n.locale)}}</td>
|
||||
<td>{{route.agencyName}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div v-if="ticket.description || ticket.shipFk" class="text-area">
|
||||
<p>{{ticket.description}}</p>
|
||||
<p v-if="ticket.shipFk">{{$t('stowaway')}}: {{ticket.shipFk}}</p>
|
||||
<div class="contained">
|
||||
<table class="middle centered" width="70%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<p class="small">Hora inicio</p>
|
||||
</td>
|
||||
<td>
|
||||
<p class="small">Hora fin</p>
|
||||
</td>
|
||||
<td class="gap"></td>
|
||||
<td>
|
||||
<p class="small">Km inicio</p>
|
||||
</td>
|
||||
<td>
|
||||
<p class="small">Km fin</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td v-for="i in 2">
|
||||
<div class="field rectangle">
|
||||
<span></span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="gap"></td>
|
||||
<td v-for="i in 2">
|
||||
<div class="field rectangle">
|
||||
<span></span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Route ticket list -->
|
||||
<div class="no-page-break" v-for="ticket in route.tickets">
|
||||
<div>
|
||||
<table class="column-oriented repeatable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="number">{{$t('order')}}</th>
|
||||
<th class="number">{{$t('ticket')}}</th>
|
||||
<th width="50%">{{$t('client')}}</th>
|
||||
<th class="number">{{$t('address')}}</th>
|
||||
<th class="number">{{$t('packages')}}</th>
|
||||
<th>{{$t('packagingType')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="number">{{ticket.priority}}</td>
|
||||
<td class="number">{{ticket.id}}</td>
|
||||
<td width="50%">{{ticket.clientFk}} {{ticket.addressName}}</td>
|
||||
<td v-if="ticket.addressFk" class="number">
|
||||
{{ticket.addressFk.toString().substr(0,
|
||||
ticket.addressFk.toString().length - 3)}}
|
||||
<span class="black-container">
|
||||
{{ticket.addressFk.toString().substr(-3, 3)}}
|
||||
</span>
|
||||
</td>
|
||||
<td class="number">{{ticket.packages}}</td>
|
||||
<td>{{ticket.itemPackingTypes}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<table width="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('street')}}</th>
|
||||
<td>{{ticket.street}}</td>
|
||||
<th class="font gray align-right">{{$t('postcode')}}</th>
|
||||
<td>{{ticket.postalCode}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('city')}}</th>
|
||||
<td>{{ticket.city}}</td>
|
||||
<th class="font gray align-right">{{$t('agency')}}</th>
|
||||
<td>{{ticket.ticketAgency}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('mobile')}}</th>
|
||||
<td>{{ticket.mobile}}</td>
|
||||
<th class="font gray align-right">{{$t('phone')}}</th>
|
||||
<td>{{ticket.phone}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('warehouse')}}</th>
|
||||
<td>{{ticket.warehouseName}}</td>
|
||||
<th class="font gray align-right">{{$t('salesPerson')}}</th>
|
||||
<td>{{ticket.salesPersonName}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="font gray align-right">{{$t('import')}}</th>
|
||||
<td>{{ticket.import | currency('EUR', $i18n.locale)}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div v-if="ticket.description || ticket.shipFk" class="text-area">
|
||||
<p>{{ticket.description}}</p>
|
||||
<p v-if="ticket.shipFk">{{$t('stowaway')}}: {{ticket.shipFk}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Footer block -->
|
||||
<report-footer id="pageFooter"
|
||||
v-bind:left-text="$t('routeId', [routeId])"
|
||||
v-bind="$props">
|
||||
</report-footer>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</div>
|
||||
<!-- Footer block -->
|
||||
<report-footer id="pageFooter"
|
||||
v-bind:left-text="$t('routeId', [routeId])"
|
||||
v-bind="$props">
|
||||
</report-footer>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -30,7 +30,7 @@ module.exports = {
|
|||
return this.rawSqlFromDef('routes', [routesId]);
|
||||
},
|
||||
fetchTickets(routesId) {
|
||||
return this.rawSqlFromDef('tickets', [routesId]);
|
||||
return this.rawSqlFromDef('tickets', [routesId, routesId]);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
|
|
|
@ -10,6 +10,7 @@ order: Orden
|
|||
client: Cliente
|
||||
address: Consignatario
|
||||
packages: Bultos
|
||||
packagingType: Encajado
|
||||
street: Dirección
|
||||
postcode: Código Postal
|
||||
city: Ciudad
|
||||
|
|
|
@ -18,8 +18,9 @@ SELECT
|
|||
am.name ticketAgency,
|
||||
tob.description,
|
||||
s.shipFk,
|
||||
u.nickName salesPersonName
|
||||
FROM route r
|
||||
u.nickName salesPersonName,
|
||||
ipkg.itemPackingTypes
|
||||
FROM route r
|
||||
LEFT JOIN ticket t ON t.routeFk = r.id
|
||||
LEFT JOIN address a ON a.id = t.addressFk
|
||||
LEFT JOIN client c ON c.id = t.clientFk
|
||||
|
@ -30,5 +31,15 @@ FROM route r
|
|||
LEFT JOIN warehouse wh ON wh.id = t.warehouseFk
|
||||
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
|
||||
LEFT JOIN stowaway s ON s.id = t.id
|
||||
WHERE r.id IN(?)
|
||||
ORDER BY t.priority, t.id
|
||||
LEFT JOIN (
|
||||
SELECT t.id AS ticketFk,
|
||||
GROUP_CONCAT(DISTINCT(i.itemPackingTypeFk)) AS itemPackingTypes
|
||||
FROM route r
|
||||
JOIN ticket t ON t.routeFk = r.id
|
||||
JOIN sale s ON s.ticketFk = t.id
|
||||
JOIN item i ON i.id = s.itemFk
|
||||
WHERE r.id IN (?)
|
||||
GROUP BY t.id
|
||||
) ipkg ON ipkg.ticketFk = t.id
|
||||
WHERE r.id IN (?)
|
||||
ORDER BY t.priority, t.id;
|
|
@ -1,9 +1,11 @@
|
|||
SELECT
|
||||
r.id,
|
||||
r.amountPaid,
|
||||
r.amountUnpaid,
|
||||
cr.amount AS amountUnpaid,
|
||||
r.payed,
|
||||
r.companyFk
|
||||
FROM receipt r
|
||||
JOIN client c ON c.id = r.clientFk
|
||||
JOIN vn.clientRisk cr ON cr.clientFk = c.id
|
||||
AND cr.companyFk = r.companyFk
|
||||
WHERE r.id = ?
|
Loading…
Reference in New Issue