merge
gitea/salix/dev This commit has test failures
Details
gitea/salix/dev This commit has test failures
Details
This commit is contained in:
commit
413d2f2855
|
@ -23,7 +23,7 @@ export default {
|
|||
clientsIndex: {
|
||||
searchClientInput: `${components.vnTextfield}`,
|
||||
searchButton: `vn-searchbar vn-icon[icon="search"]`,
|
||||
searchResult: `vn-item-client a`,
|
||||
searchResult: `vn-client-index .vn-list-item`,
|
||||
createClientButton: `${components.vnFloatButton}`,
|
||||
othersButton: `vn-left-menu li[name="Others"] > a`
|
||||
},
|
||||
|
|
|
@ -152,44 +152,46 @@ vn-tool-bar {
|
|||
.vn-list {
|
||||
max-width: 36em;
|
||||
margin: 0 auto;
|
||||
}
|
||||
a.vn-list-item {
|
||||
@extend %clickable;
|
||||
}
|
||||
.vn-list-item {
|
||||
padding: $pad-medium;
|
||||
border-bottom: $border-thin solid $color-spacer;
|
||||
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
a.vn-list-item {
|
||||
@extend %clickable;
|
||||
}
|
||||
.vn-list-item {
|
||||
border-bottom: $border-thin solid $color-spacer;
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
|
||||
& > vn-horizontal {
|
||||
& > vn-one {
|
||||
overflow: hidden;
|
||||
}
|
||||
& > .buttons {
|
||||
align-items: center;
|
||||
& > vn-horizontal {
|
||||
padding: $pad-medium;
|
||||
|
||||
vn-icon-button {
|
||||
opacity: .4;
|
||||
color: $color-main;
|
||||
margin-left: .5em;
|
||||
transition: opacity 250ms ease-out;
|
||||
padding: 0;
|
||||
font-size: 2em;
|
||||
& > vn-one {
|
||||
overflow: hidden;
|
||||
}
|
||||
& > .buttons {
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
vn-icon-button {
|
||||
opacity: .4;
|
||||
color: $color-main;
|
||||
margin-left: .5em;
|
||||
transition: opacity 250ms ease-out;
|
||||
padding: 0;
|
||||
font-size: 2em;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
vn-empty-rows.vn-list-item {
|
||||
text-align: center;
|
||||
padding: 1.5em;
|
||||
box-sizing: border-box;
|
||||
vn-empty-rows {
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 1.5em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
/** START - FORM ELEMENTS DISABLED **/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"module": "agency",
|
||||
"name": "Agencies",
|
||||
"icon" : "local_shipping",
|
||||
"icon" : "icon-delivery",
|
||||
"validations" : true,
|
||||
"menu": [
|
||||
{"state": "zone.card.basicData", "icon": "settings"},
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('Client card', () => {
|
||||
describe('Client get', () => {
|
||||
it('should call the card() method to receive a formated card of Bruce Wayne', async() => {
|
||||
let id = 101;
|
||||
let result = await app.models.Client.getCard(id);
|
||||
|
||||
expect(result.id).toEqual(101);
|
||||
expect(result.name).toEqual('Bruce Wayne');
|
||||
expect(result.debt).toEqual(579.1);
|
||||
expect(result.debt).toEqual(595.81);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,7 +17,7 @@ describe('client summary()', () => {
|
|||
it('should return a summary object containing debt', async() => {
|
||||
let result = await app.models.Client.summary(101);
|
||||
|
||||
expect(result.debt.debt).toEqual(579.1);
|
||||
expect(result.debt.debt).toEqual(595.81);
|
||||
});
|
||||
|
||||
it('should return a summary object containing averageInvoiced', async() => {
|
||||
|
|
|
@ -25,7 +25,7 @@ class Controller {
|
|||
tooltip: 'Client ticket list'
|
||||
},
|
||||
btnTwo: {
|
||||
icon: 'shopping_cart',
|
||||
icon: 'icon-basket',
|
||||
state: `order.create({clientFk: ${value.id}})`,
|
||||
tooltip: 'New order'
|
||||
}
|
||||
|
|
|
@ -17,11 +17,42 @@
|
|||
</vn-searchbar>
|
||||
</vn-card>
|
||||
<vn-card margin-medium-v>
|
||||
<vn-item-client
|
||||
class="searchResult"
|
||||
<a
|
||||
ng-repeat="client in clients track by client.id"
|
||||
client="::client">
|
||||
</vn-item-client>
|
||||
ui-sref="client.card.summary({ id: {{::client.id}} })"
|
||||
translate-attr="{title: 'View client'}"
|
||||
class="vn-list-item searchResult">
|
||||
<vn-horizontal ng-click="$ctrl.onClick($event)">
|
||||
<vn-one>
|
||||
<h6>{{::client.name}}</h6>
|
||||
<vn-label-value label="Id"
|
||||
value="{{::client.id}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Phone"
|
||||
value="{{::client.phone | phone}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Town/City"
|
||||
value="{{::client.city}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Email"
|
||||
value="{{::client.email}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-horizontal class="buttons">
|
||||
<vn-icon-button
|
||||
ng-click="$ctrl.preview($event)"
|
||||
vn-tooltip="Preview"
|
||||
icon="desktop_windows">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
</vn-horizontal>
|
||||
</a>
|
||||
<vn-empty-rows translate ng-if="model.data.length === 0">
|
||||
No results
|
||||
</vn-empty-rows>
|
||||
<vn-empty-rows translate ng-if="model.data === null">
|
||||
Enter a new search
|
||||
</vn-empty-rows>
|
||||
</vn-card>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import ngModule from '../module';
|
||||
import './item-client';
|
||||
|
||||
export default class Controller {
|
||||
constructor($scope, $stateParams) {
|
||||
|
@ -33,7 +32,13 @@ export default class Controller {
|
|||
}
|
||||
}
|
||||
|
||||
openSummary(client) {
|
||||
onClick(event) {
|
||||
if (event.defaultPrevented)
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
openSummary(client, event) {
|
||||
event.preventDefault();
|
||||
this.clientSelected = client;
|
||||
this.$.dialogSummaryClient.show();
|
||||
}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
<a
|
||||
ui-sref="client.card.summary({ id: {{::$ctrl.client.id}} })"
|
||||
translate-attr="{title: 'View client'}"
|
||||
class="vn-list-item">
|
||||
<vn-horizontal ng-click="$ctrl.onClick($event)">
|
||||
<vn-one>
|
||||
<h6>{{::$ctrl.client.name}}</h6>
|
||||
<vn-label-value label="Id"
|
||||
value="{{::$ctrl.client.id}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Phone"
|
||||
value="{{::$ctrl.client.phone | phone}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Town/City"
|
||||
value="{{::$ctrl.client.city}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Email"
|
||||
value="{{::$ctrl.client.email}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-horizontal class="buttons">
|
||||
<vn-icon-button
|
||||
ng-click="$ctrl.preview($event)"
|
||||
vn-tooltip="Preview"
|
||||
icon="desktop_windows">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
</vn-horizontal>
|
||||
</a>
|
|
@ -1,24 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
onClick(event) {
|
||||
if (event.defaultPrevented)
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
|
||||
preview(event) {
|
||||
event.preventDefault();
|
||||
this.list.openSummary(this.client);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnItemClient', {
|
||||
template: require('./item-client.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
},
|
||||
require: {
|
||||
list: '^vnClientIndex'
|
||||
}
|
||||
});
|
|
@ -1,3 +0,0 @@
|
|||
vn-item-client {
|
||||
display: block;
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
{"state": "client.card.basicData", "icon": "settings"},
|
||||
{"state": "client.card.fiscalData", "icon": "account_balance"},
|
||||
{"state": "client.card.billingData", "icon": "icon-payment"},
|
||||
{"state": "client.card.address.index", "icon": "local_shipping"},
|
||||
{"state": "client.card.address.index", "icon": "icon-delivery"},
|
||||
{"state": "client.card.note.index", "icon": "insert_drive_file"},
|
||||
{"state": "client.card.credit.index", "icon": "credit_card"},
|
||||
{"state": "client.card.greuge.index", "icon": "work"},
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"module": "item",
|
||||
"name": "Items",
|
||||
"icon": "inbox",
|
||||
"icon": "icon-item",
|
||||
"validations" : true,
|
||||
"dependencies": ["worker", "client", "ticket"],
|
||||
"menu": [
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"module": "order",
|
||||
"name": "Orders",
|
||||
"icon": "shopping_cart",
|
||||
"icon": "icon-basket",
|
||||
"validations": true,
|
||||
"dependencies": ["worker", "item", "ticket"],
|
||||
"menu": [
|
||||
{"state": "order.card.basicData", "icon": "settings"},
|
||||
{"state": "order.card.catalog", "icon": "shopping_cart"},
|
||||
{"state": "order.card.catalog", "icon": "icon-basket"},
|
||||
{"state": "order.card.volume", "icon": "icon-volume"},
|
||||
{"state": "order.card.line", "icon": "icon-lines"}
|
||||
],
|
||||
|
|
|
@ -25,23 +25,17 @@ module.exports = Self => {
|
|||
Self.filter = async filter => {
|
||||
const stmt = new ParameterizedSQL(
|
||||
`SELECT
|
||||
e.id,
|
||||
e.ticketFk,
|
||||
e.isBox,
|
||||
i1.name namePackage,
|
||||
e.counter,
|
||||
e.checked,
|
||||
i2.name nameBox,
|
||||
e.itemFk,
|
||||
u.nickname userNickname,
|
||||
u.id userId,
|
||||
e.created
|
||||
e.id, e.ticketFk, e.isBox,
|
||||
i1.name namePackage, e.counter,
|
||||
e.checked, i2.name nameBox,
|
||||
e.itemFk, u.nickname userNickname,
|
||||
u.id userId, e.created, e.externalId
|
||||
FROM
|
||||
vn.expedition e
|
||||
LEFT JOIN vn.item i2 ON i2.id = e.itemFk
|
||||
INNER JOIN vn.item i1 ON i1.id = e.isBox
|
||||
LEFT JOIN vn.worker w ON w.id = e.workerFk
|
||||
JOIN account.user u ON u.id = w.id
|
||||
JOIN account.user u ON u.id = w.userFk
|
||||
`);
|
||||
stmt.merge(Self.buildSuffix(filter, 'e'));
|
||||
|
||||
|
|
|
@ -4,6 +4,6 @@ describe('ticket getTaxes()', () => {
|
|||
it('should return the tax of a given ticket', async() => {
|
||||
let result = await app.models.Ticket.getTaxes(1);
|
||||
|
||||
expect(result[0].tax).toEqual(7.44);
|
||||
expect(result[0].tax).toEqual(7.64);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ describe('ticket getTotal()', () => {
|
|||
it('should return the total of a ticket', async() => {
|
||||
let result = await app.models.Ticket.getTotal(1);
|
||||
|
||||
expect(result).toEqual(155.89);
|
||||
expect(result).toEqual(158.09);
|
||||
});
|
||||
|
||||
it(`should return zero if the ticket doesn't have lines`, async() => {
|
||||
|
|
|
@ -4,7 +4,7 @@ describe('ticket getVAT()', () => {
|
|||
it('should call the getVAT method and return the response', async() => {
|
||||
await app.models.Ticket.getVAT(1)
|
||||
.then(response => {
|
||||
expect(response).toEqual(20.29);
|
||||
expect(response).toEqual(20.49);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('ticket subtotal()', () => {
|
||||
it('should return the subtotal of a ticket', async() => {
|
||||
let result = await app.models.Ticket.subtotal(1);
|
||||
|
||||
expect(result).toEqual(137.60);
|
||||
});
|
||||
|
||||
it(`should return zero if the ticket doesn't have lines`, async() => {
|
||||
let result = await app.models.Ticket.subtotal(13);
|
||||
|
||||
expect(result).toEqual(0.00);
|
||||
});
|
||||
});
|
|
@ -14,21 +14,21 @@ describe('ticket summary()', () => {
|
|||
expect(result.sales.length).toEqual(4);
|
||||
});
|
||||
|
||||
it('should return a summary object containing subTotal for 1 ticket', async() => {
|
||||
it('should return a summary object containing subtotal for 1 ticket', async() => {
|
||||
let result = await app.models.Ticket.summary(1);
|
||||
|
||||
expect(Math.round(result.subTotal * 100) / 100).toEqual(135.60);
|
||||
expect(Math.round(result.subtotal * 100) / 100).toEqual(137.60);
|
||||
});
|
||||
|
||||
it('should return a summary object containing VAT for 1 ticket', async() => {
|
||||
let result = await app.models.Ticket.summary(1);
|
||||
|
||||
expect(Math.round(result.VAT * 100) / 100).toEqual(20.29);
|
||||
expect(Math.round(result.vat * 100) / 100).toEqual(20.49);
|
||||
});
|
||||
|
||||
it('should return a summary object containing total for 1 ticket', async() => {
|
||||
let result = await app.models.Ticket.summary(1);
|
||||
let total = result.subTotal + result.VAT;
|
||||
let total = result.subtotal + result.vat;
|
||||
let expectedTotal = Math.round(total * 100) / 100;
|
||||
|
||||
expect(result.total).toEqual(expectedTotal);
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('subtotal', {
|
||||
description: 'Returns the total of a ticket',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'ticket id',
|
||||
http: {source: 'path'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'number',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/subtotal`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.subtotal = async ticketFk => {
|
||||
const sale = Self.app.models.Sale;
|
||||
const ticketSales = await sale.find({where: {ticketFk}});
|
||||
const ticketService = Self.app.models.TicketService;
|
||||
const ticketServices = await ticketService.find({where: {ticketFk}});
|
||||
|
||||
let subtotal = 0.00;
|
||||
ticketSales.forEach(sale => {
|
||||
subtotal += sale.price * sale.quantity * ((100 - sale.discount) / 100);
|
||||
});
|
||||
|
||||
ticketServices.forEach(service => {
|
||||
subtotal += service.price * service.quantity;
|
||||
});
|
||||
|
||||
|
||||
return Math.round(subtotal * 100) / 100;
|
||||
};
|
||||
};
|
|
@ -23,9 +23,9 @@ module.exports = Self => {
|
|||
let models = Self.app.models;
|
||||
let summaryObj = await getTicketData(Self, ticketFk);
|
||||
summaryObj.sales = await getSales(models.Sale, ticketFk);
|
||||
summaryObj.subTotal = getSubTotal(summaryObj.sales);
|
||||
summaryObj.VAT = await models.Ticket.getVAT(ticketFk);
|
||||
summaryObj.total = await models.Ticket.getTotal(ticketFk);
|
||||
summaryObj.subtotal = await models.Ticket.subtotal(ticketFk);
|
||||
summaryObj.vat = await models.Ticket.getVAT(ticketFk);
|
||||
summaryObj.total = summaryObj.subtotal + summaryObj.vat;
|
||||
summaryObj.packagings = await models.TicketPackaging.find({
|
||||
where: {ticketFk: ticketFk},
|
||||
include: [{relation: 'packaging',
|
||||
|
@ -149,14 +149,4 @@ module.exports = Self => {
|
|||
};
|
||||
return await Self.app.models.TicketRequest.find(filter);
|
||||
}
|
||||
|
||||
function getSubTotal(sales) {
|
||||
let subTotal = 0.00;
|
||||
|
||||
sales.forEach(sale => {
|
||||
subTotal += sale.quantity * sale.price;
|
||||
});
|
||||
|
||||
return subTotal;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@ module.exports = Self => {
|
|||
require('../methods/ticket/summary')(Self);
|
||||
require('../methods/ticket/getTotal')(Self);
|
||||
require('../methods/ticket/getTaxes')(Self);
|
||||
require('../methods/ticket/subtotal')(Self);
|
||||
require('../methods/ticket/componentUpdate')(Self);
|
||||
require('../methods/ticket/new')(Self);
|
||||
require('../methods/ticket/isEditable')(Self);
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th></vn-th>
|
||||
<vn-th field="itemFk" number>Expedition</vn-th>
|
||||
<vn-th field="itemFk" number>Envialia</vn-th>
|
||||
<vn-th field="itemFk" number>Item</vn-th>
|
||||
<vn-th field="name">Name</vn-th>
|
||||
<vn-th field="isBox">Package type</vn-th>
|
||||
|
@ -30,6 +32,8 @@
|
|||
vn-tooltip="Delete expedition">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
<vn-td number>{{expedition.id | zeroFill:6}}</vn-td>
|
||||
<vn-td number>{{expedition.externalId | zeroFill:6}}</vn-td>
|
||||
<vn-td number>
|
||||
<span
|
||||
ng-class="{link: expedition.itemFk}"
|
||||
|
@ -41,7 +45,6 @@
|
|||
<vn-td>{{::expedition.nameBox}}</vn-td>
|
||||
<vn-td number>{{::expedition.counter}}</vn-td>
|
||||
<vn-td number>{{::expedition.checked}}</vn-td>
|
||||
<vn-td>{{::expedition.userNickname}}</vn-td>
|
||||
<vn-td expand>
|
||||
<span
|
||||
class="link"
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
</vn-button>
|
||||
</vn-tool-bar>
|
||||
<vn-one class="taxes" ng-if="$ctrl.sales.length > 0">
|
||||
<p><vn-label translate>Subtotal</vn-label> {{$ctrl.subTotal | currency: 'EUR':2}}</p>
|
||||
<p><vn-label translate>Subtotal</vn-label> {{$ctrl.subtotal | currency: 'EUR':2}}</p>
|
||||
<p><vn-label translate>VAT</vn-label> {{$ctrl.VAT | currency: 'EUR':2}}</p>
|
||||
<p><vn-label><strong>Total</strong></vn-label> <strong>{{$ctrl.total | currency: 'EUR':2}}</strong></p>
|
||||
</vn-one>
|
||||
|
|
|
@ -36,9 +36,10 @@ class Controller {
|
|||
}
|
||||
|
||||
loadSubTotal() {
|
||||
this.subTotal = 0.0;
|
||||
if (!this.sales) return;
|
||||
this.subTotal = this.sales.reduce((sum, sale) => sum + this.getSaleTotal(sale), 0.0);
|
||||
if (!this.$stateParams.id || !this.sales) return;
|
||||
this.$http.get(`/ticket/api/Tickets/${this.$stateParams.id}/subtotal`).then(res => {
|
||||
this.subtotal = res.data || 0.0;
|
||||
});
|
||||
}
|
||||
|
||||
getSaleTotal(sale) {
|
||||
|
@ -54,7 +55,7 @@ class Controller {
|
|||
}
|
||||
|
||||
get total() {
|
||||
return this.subTotal + this.VAT;
|
||||
return this.subtotal + this.VAT;
|
||||
}
|
||||
|
||||
onMoreOpen() {
|
||||
|
|
|
@ -41,6 +41,7 @@ describe('Ticket', () => {
|
|||
$httpBackend = _$httpBackend_;
|
||||
$httpBackend.whenGET(/api\/Tickets\/1\/getSales.*/).respond(sales);
|
||||
$httpBackend.whenGET(`/ticket/api/Tickets/1/getVAT`).respond(200, 10.5);
|
||||
$httpBackend.whenGET(`/ticket/api/Tickets/1/subtotal`).respond(200, 227.5);
|
||||
|
||||
$element = $compile('<vn-ticket-sale ticket="ticket"></vn-ticket-sale>')($scope);
|
||||
controller = $element.controller('vnTicketSale');
|
||||
|
@ -67,9 +68,9 @@ describe('Ticket', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('total/VAT/subTotal properties', () => {
|
||||
describe('total/VAT/subtotal properties', () => {
|
||||
it('should fill total, VAT and subTotal', () => {
|
||||
expect(controller.subTotal).toEqual(227.5);
|
||||
expect(controller.subtotal).toEqual(227.5);
|
||||
expect(controller.VAT).toEqual(10.5);
|
||||
expect(controller.total).toEqual(238);
|
||||
});
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-one class="taxes">
|
||||
<p><vn-label translate>Subtotal</vn-label> {{$ctrl.summary.subTotal | currency: 'EUR':2}}</p>
|
||||
<p><vn-label translate>VAT</vn-label> {{$ctrl.summary.VAT | currency: 'EUR':2}}</p>
|
||||
<p><vn-label translate>Subtotal</vn-label> {{$ctrl.summary.subtotal | currency: 'EUR':2}}</p>
|
||||
<p><vn-label translate>VAT</vn-label> {{$ctrl.summary.vat | currency: 'EUR':2}}</p>
|
||||
<p><vn-label><strong>Total</strong></vn-label> <strong>{{$ctrl.summary.total | currency: 'EUR':2}}</strong></p>
|
||||
</vn-one>
|
||||
<vn-auto name="sales">
|
||||
|
|
|
@ -48,6 +48,12 @@
|
|||
</vn-horizontal>
|
||||
</vn-horizontal>
|
||||
</a>
|
||||
<vn-empty-rows translate ng-if="model.data.length === 0">
|
||||
No results
|
||||
</vn-empty-rows>
|
||||
<vn-empty-rows translate ng-if="model.data === null">
|
||||
Enter a new search
|
||||
</vn-empty-rows>
|
||||
</vn-card>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
USE `vn`;
|
||||
DROP procedure IF EXISTS `ticketGetTax`;
|
||||
|
||||
DELIMITER $$
|
||||
USE `vn`$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `ticketGetTax`()
|
||||
READS SQL DATA
|
||||
BEGIN
|
||||
/**
|
||||
* Calcula la base imponible, el IVA y el recargo de equivalencia para
|
||||
* un conjunto de tickets.
|
||||
*
|
||||
* @table tmp.ticket(ticketFk) Identificadores de los tickets a calcular
|
||||
* @return tmp.ticketAmount
|
||||
* @return tmp.ticketTax Impuesto desglosado para cada ticket.
|
||||
|
||||
*/
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.addressCompany;
|
||||
CREATE TEMPORARY TABLE tmp.addressCompany
|
||||
(INDEX (addressFk, companyFk))
|
||||
ENGINE = MEMORY
|
||||
SELECT DISTINCT t.addressFk, t.companyFk
|
||||
FROM tmp.ticket tmpTicket
|
||||
JOIN ticket t ON t.id = tmpTicket.ticketFk;
|
||||
|
||||
CALL addressTaxArea ();
|
||||
|
||||
|
||||
/** Solo se calcula la base imponible (taxableBase) y el impuesto se calculará posteriormente
|
||||
* No se debería cambiar el sistema por problemas con los decimales
|
||||
*/
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticketTax;
|
||||
CREATE TEMPORARY TABLE tmp.ticketTax
|
||||
(INDEX (ticketFk))
|
||||
ENGINE = MEMORY
|
||||
SELECT tmpTicket.ticketFk,
|
||||
bp.pgcFk,
|
||||
SUM(s.quantity * s.price * (100 - s.discount)/100 ) AS taxableBase,
|
||||
pgc.rate,
|
||||
tc.code
|
||||
FROM tmp.ticket tmpTicket
|
||||
JOIN sale s ON s.ticketFk = tmpTicket.ticketFk
|
||||
JOIN item i ON i.id = s.itemFk
|
||||
JOIN ticket t ON t.id = tmpTicket.ticketFk
|
||||
JOIN supplier su ON su.id = t.companyFk
|
||||
JOIN tmp.addressTaxArea ata
|
||||
ON ata.addressFk = t.addressFk AND ata.companyFk = t.companyFk
|
||||
JOIN itemTaxCountry itc
|
||||
ON itc.itemFk = i.id AND itc.countryFk = su.countryFk
|
||||
JOIN bookingPlanner bp
|
||||
ON bp.countryFk = su.countryFk
|
||||
AND bp.taxAreaFk = ata.areaFk
|
||||
AND bp.taxClassFk = itc.taxClassFk
|
||||
JOIN pgc ON pgc.code = bp.pgcFk
|
||||
JOIN taxClass tc ON tc.id = bp.taxClassFk
|
||||
GROUP BY tmpTicket.ticketFk, pgc.code,pgc.rate
|
||||
HAVING taxableBase != 0;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticketServiceTax;
|
||||
CREATE TEMPORARY TABLE tmp.ticketServiceTax
|
||||
(INDEX (ticketFk))
|
||||
ENGINE = MEMORY
|
||||
SELECT tt.ticketFk,
|
||||
SUM(ts.quantity * ts.price) AS taxableBase,
|
||||
pgc.rate,
|
||||
tc.code
|
||||
FROM tmp.ticketTax tt
|
||||
JOIN ticketService ts ON ts.ticketFk = tt.ticketFk
|
||||
JOIN ticket t ON t.id = tt.ticketFk
|
||||
JOIN supplier su ON su.id = t.companyFk
|
||||
JOIN tmp.addressTaxArea ata
|
||||
ON ata.addressFk = t.addressFk AND ata.companyFk = t.companyFk
|
||||
JOIN bookingPlanner bp
|
||||
ON bp.countryFk = su.countryFk
|
||||
AND bp.taxAreaFk = ata.areaFk
|
||||
AND bp.taxClassFk = ts.taxClassFk
|
||||
JOIN pgc ON pgc.code = bp.pgcFk AND pgc.rate = tt.rate
|
||||
JOIN taxClass tc ON tc.id = bp.taxClassFk
|
||||
GROUP BY tt.ticketFk, tt.code,tt.rate
|
||||
HAVING taxableBase != 0;
|
||||
|
||||
UPDATE tmp.ticketTax tt
|
||||
JOIN tmp.ticketServiceTax ts ON tt.ticketFk = ts.ticketFk AND tt.code = ts.code AND tt.rate = ts.rate
|
||||
SET tt.taxableBase = tt.taxableBase + ts.taxableBase;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticketAmount;
|
||||
CREATE TEMPORARY TABLE tmp.ticketAmount
|
||||
(INDEX (ticketFk))
|
||||
ENGINE = MEMORY
|
||||
SELECT ticketFk, taxableBase, SUM(CAST(taxableBase * rate / 100 AS DECIMAL(10, 2))) tax,code
|
||||
FROM tmp.ticketTax
|
||||
GROUP BY ticketFk, code;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.addressCompany;
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.addressTaxArea;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
|
@ -0,0 +1,34 @@
|
|||
DROP PROCEDURE IF EXISTS vn.ticketGetTaxAdd;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`ticketGetTaxAdd`(vTicketFk INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Añade un ticket a la tabla tmp.ticket para calcular
|
||||
* el IVA y el recargo de equivalencia y devuelve el resultado.
|
||||
*/
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticket;
|
||||
CREATE TEMPORARY TABLE tmp.ticket
|
||||
ENGINE = MEMORY
|
||||
SELECT vTicketFk ticketFk;
|
||||
|
||||
CALL vn.ticketGetTax();
|
||||
|
||||
SELECT
|
||||
tt.ticketFk,
|
||||
CAST(tt.taxableBase AS DECIMAL(10, 2)) AS taxableBase,
|
||||
CAST(tt.rate * tt.taxableBase / 100 AS DECIMAL(10, 2)) AS tax,
|
||||
pgc.*,
|
||||
CAST(IF(pe.equFk IS NULL, taxableBase, 0) AS DECIMAL(10, 2)) AS Base,
|
||||
pgc.rate / 100 as vatPercent
|
||||
FROM tmp.ticketTax tt
|
||||
JOIN vn.pgc ON pgc.code = tt.pgcFk
|
||||
LEFT JOIN vn.pgcEqu pe ON pe.equFk = pgc.code;
|
||||
|
||||
DROP TEMPORARY TABLE tmp.ticket;
|
||||
DROP TEMPORARY TABLE tmp.ticketTax;
|
||||
DROP TEMPORARY TABLE tmp.ticketAmount;
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
Loading…
Reference in New Issue