Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into dev
gitea/salix/dev This commit has test failures
Details
gitea/salix/dev This commit has test failures
Details
This commit is contained in:
commit
02569aeea4
|
@ -163,6 +163,10 @@ export default {
|
|||
firstRiskLineBalance: 'vn-client-risk-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)'
|
||||
|
||||
},
|
||||
webPayment: {
|
||||
confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]',
|
||||
firstPaymentConfirmed: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon[icon="check"]'
|
||||
},
|
||||
itemsIndex: {
|
||||
goBackToModuleIndexButton: `vn-ticket-descriptor a[href="#!/ticket/index"]`,
|
||||
createItemButton: `${components.vnFloatButton}`,
|
||||
|
@ -269,7 +273,7 @@ export default {
|
|||
sale: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr',
|
||||
firstSaleItemId: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > span',
|
||||
popoverDiaryButton: 'vn-ticket-summary vn-item-descriptor-popover vn-item-descriptor vn-icon[icon="icon-transaction"]',
|
||||
firstSaleQuantity: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4)',
|
||||
firstSaleQuantity: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3)',
|
||||
firstSaleDiscount: 'vn-ticket-summary [name="sales"] vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6)'
|
||||
},
|
||||
ticketsIndex: {
|
||||
|
@ -337,18 +341,18 @@ export default {
|
|||
firstSaleQuantity: `vn-textfield[model="sale.quantity"]:nth-child(1) input`,
|
||||
firstSaleQuantityClearInput: `vn-textfield[model="sale.quantity"] div.suffix > i`,
|
||||
firstSaleID: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(4) > span',
|
||||
firstSalePrice: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(7)',
|
||||
firstSalePrice: 'vn-ticket-sale:nth-child(1) vn-tr:nth-child(1) > vn-td:nth-child(7) > span',
|
||||
firstSalePriceInput: 'vn-ticket-sale:nth-child(1) > vn-vertical > vn-popover.edit.dialog-summary.ng-isolate-scope.vn-popover.shown > div > div.content > div > vn-textfield',
|
||||
firstSaleDiscount: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(8)',
|
||||
firstSaleDiscount: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(8) > span',
|
||||
firstSaleDiscountInput: 'vn-ticket-sale:nth-child(1) vn-ticket-sale-edit-discount > div > vn-textfield > div > div > div.infix > input.ng-not-empty',
|
||||
firstSaleImport: 'vn-ticket-sale:nth-child(1) vn-td:nth-child(9)',
|
||||
firstSaleReservedIcon: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td:nth-child(2) > vn-icon:nth-child(3)',
|
||||
firstSaleColour: `vn-ticket-sale vn-tr:nth-child(1) vn-td:nth-child(5) section:nth-child(1)`,
|
||||
firstSaleLength: `vn-ticket-sale vn-tr:nth-child(1) vn-td:nth-child(5) section:nth-child(3)`,
|
||||
firstSaleColour: `vn-ticket-sale vn-tr:nth-child(1) vn-td:nth-child(6) section:nth-child(1)`,
|
||||
firstSaleLength: `vn-ticket-sale vn-tr:nth-child(1) vn-td:nth-child(6) section:nth-child(3)`,
|
||||
firstSaleCheckbox: `vn-ticket-sale vn-tr:nth-child(1) vn-check[field="sale.checked"] md-checkbox`,
|
||||
secondSaleClaimIcon: 'vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(2) > a > vn-icon',
|
||||
secondSaleColour: `vn-ticket-sale vn-tr:nth-child(2) vn-td:nth-child(5) section:nth-child(5)`,
|
||||
secondSalePrice: `vn-ticket-sale vn-tr:nth-child(2) vn-td:nth-child(7)`,
|
||||
secondSaleColour: `vn-ticket-sale vn-tr:nth-child(2) vn-td:nth-child(6) section:nth-child(5)`,
|
||||
secondSalePrice: `vn-ticket-sale vn-tr:nth-child(2) vn-td:nth-child(7) > span`,
|
||||
secondSaleDiscount: `vn-ticket-sale vn-tr:nth-child(2) vn-td:nth-child(8)`,
|
||||
secondSaleImport: `vn-ticket-sale vn-tr:nth-child(2) vn-td:nth-child(9)`,
|
||||
secondSaleText: `vn-table div > vn-tbody > vn-tr:nth-child(2)`,
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import createNightmare from '../../helpers/nightmare';
|
||||
|
||||
// #860 E2E client/client/src/web-payment/index.js missing fixtures for another client
|
||||
xdescribe('Client web Payment', () => {
|
||||
const nightmare = createNightmare();
|
||||
|
||||
describe('as employee', () => {
|
||||
beforeAll(() => {
|
||||
nightmare
|
||||
.loginAndModule('employee', 'client')
|
||||
.accessToSearchResult('Bruce Wayne')
|
||||
.accessToSection('client.card.webPayment');
|
||||
});
|
||||
|
||||
it('should not be able to confirm payments', async() => {
|
||||
let exists = await nightmare
|
||||
.exists(selectors.webPayment.confirmFirstPaymentButton);
|
||||
|
||||
expect(exists).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('as administrative', () => {
|
||||
beforeAll(() => {
|
||||
nightmare
|
||||
.loginAndModule('administrative', 'client')
|
||||
.accessToSearchResult('Bruce Wayne')
|
||||
.accessToSection('client.card.webPayment');
|
||||
});
|
||||
|
||||
it('should be able to confirm payments', async() => {
|
||||
let exists = await nightmare
|
||||
.waitToClick(selectors.webPayment.confirmFirstPaymentButton)
|
||||
.exists(selectors.webPayment.firstPaymentConfirmed);
|
||||
|
||||
expect(exists).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,61 @@
|
|||
import createNightmare from '../../helpers/nightmare';
|
||||
import config from '../../helpers/config.js';
|
||||
|
||||
|
||||
describe('Login path', () => {
|
||||
const nightmare = createNightmare();
|
||||
|
||||
it('should receive an error when the username is incorrect', async() => {
|
||||
const username = 'nobody';
|
||||
const password = 'nightmare';
|
||||
|
||||
const result = await nightmare
|
||||
.goto(`${config.url}/#!/login`)
|
||||
.wait(`vn-login input[name=user]`)
|
||||
.write(`vn-login input[name=user]`, username)
|
||||
.write(`vn-login input[name=password]`, password)
|
||||
.click(`vn-login input[type=submit]`)
|
||||
.waitForLastSnackbar();
|
||||
|
||||
expect(result.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should receive an error when the username is blank', async() => {
|
||||
const password = 'nightmare';
|
||||
|
||||
const result = await nightmare
|
||||
.clearInput(`vn-login input[name=user]`)
|
||||
.write(`vn-login input[name=password]`, password)
|
||||
.click(`vn-login input[type=submit]`)
|
||||
.waitForLastSnackbar();
|
||||
|
||||
expect(result.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should receive an error when the password is incorrect', async() => {
|
||||
const username = 'employee';
|
||||
const password = 'badpassword';
|
||||
|
||||
const result = await nightmare
|
||||
.write(`vn-login input[name=user]`, username)
|
||||
.write(`vn-login input[name=password]`, password)
|
||||
.click(`vn-login input[type=submit]`)
|
||||
.waitForLastSnackbar();
|
||||
|
||||
expect(result.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should log in', async() => {
|
||||
const username = 'employee';
|
||||
const password = 'nightmare';
|
||||
|
||||
const url = await nightmare
|
||||
.write(`vn-login input[name=user]`, username)
|
||||
.write(`vn-login input[name=password]`, password)
|
||||
.click(`vn-login input[type=submit]`)
|
||||
.wait('#logout')
|
||||
.parsedUrl();
|
||||
|
||||
expect(url.hash).toEqual('#!/');
|
||||
});
|
||||
});
|
|
@ -538,16 +538,16 @@ xdescribe('Ticket Edit sale path', () => {
|
|||
describe('when state is preparation and loged as Production', () => {
|
||||
it(`should not be able to edit the sale price`, async() => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.ticketSales.firstSalePrice)
|
||||
.exists(selectors.ticketSales.firstSalePriceInput);
|
||||
.wait(selectors.ticketSales.firstSaleID)
|
||||
.exists(selectors.ticketSales.firstSalePrice);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it(`should not be able to edit the sale discount`, async() => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.ticketSales.firstSaleDiscount)
|
||||
.exists(selectors.ticketSales.firstSaleDiscountInput);
|
||||
.waitToClick(selectors.ticketSales.firstSaleID)
|
||||
.exists(selectors.ticketSales.firstSaleDiscount);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
|
|
@ -22,12 +22,12 @@ module.exports = function(Self) {
|
|||
oldInstance = await fkToValue(oldInstanceFk, ctx);
|
||||
if (ctx.where && !ctx.currentInstance) {
|
||||
let fields = Object.keys(ctx.data);
|
||||
ctx.oldInstances = await Self.modelBuilder.models[ctx.Model.definition.name].find({where: ctx.where, fields: fields});
|
||||
ctx.oldInstances = await ctx.Model.app.models[ctx.Model.definition.name].find({where: ctx.where, fields: fields});
|
||||
}
|
||||
}
|
||||
if (ctx.isNewInstance) {
|
||||
if (ctx.isNewInstance)
|
||||
newInstance = await fkToValue(ctx.instance.__data, ctx);
|
||||
}
|
||||
|
||||
ctx.hookState.oldInstance = oldInstance;
|
||||
ctx.hookState.newInstance = newInstance;
|
||||
});
|
||||
|
@ -36,7 +36,7 @@ module.exports = function(Self) {
|
|||
if (ctx.where) {
|
||||
let affectedModel = ctx.Model.definition.name;
|
||||
let definition = ctx.Model.definition;
|
||||
let deletedInstances = await Self.modelBuilder.models[affectedModel].find({where: ctx.where});
|
||||
let deletedInstances = await ctx.Model.app.models[affectedModel].find({where: ctx.where});
|
||||
let relation = definition.settings.log.relation;
|
||||
|
||||
if (relation) {
|
||||
|
@ -81,12 +81,11 @@ module.exports = function(Self) {
|
|||
};
|
||||
|
||||
let transaction = {};
|
||||
if (ctx.options && ctx.options.transaction) {
|
||||
if (ctx.options && ctx.options.transaction)
|
||||
transaction = ctx.options.transaction;
|
||||
}
|
||||
|
||||
let logModel = definition.settings.log.model;
|
||||
await Self.modelBuilder.models[logModel].create(logRecord, transaction);
|
||||
await ctx.Model.app.models[logModel].create(logRecord, transaction);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -147,25 +146,23 @@ module.exports = function(Self) {
|
|||
if (changedModelValue && (!ctx.instance || !ctx.instance[changedModelValue])) {
|
||||
var where = [];
|
||||
changedModelId = [];
|
||||
let changedInstances = await Self.modelBuilder.models[definition.name].find({where: ctx.where, fields: ['id', changedModelValue]});
|
||||
let changedInstances = await ctx.Model.app.models[definition.name].find({where: ctx.where, fields: ['id', changedModelValue]});
|
||||
changedInstances.forEach(element => {
|
||||
where.push(element[changedModelValue]);
|
||||
changedModelId.push(element.id);
|
||||
});
|
||||
} else if (ctx.hookState.oldInstance) {
|
||||
} else if (ctx.hookState.oldInstance)
|
||||
where = ctx.instance[changedModelValue];
|
||||
}
|
||||
|
||||
|
||||
// Set oldInstance, newInstance, userFk and action
|
||||
let oldInstance = {};
|
||||
if (ctx.hookState.oldInstance) {
|
||||
if (ctx.hookState.oldInstance)
|
||||
Object.assign(oldInstance, ctx.hookState.oldInstance);
|
||||
}
|
||||
|
||||
let newInstance = {};
|
||||
if (ctx.hookState.newInstance) {
|
||||
if (ctx.hookState.newInstance)
|
||||
Object.assign(newInstance, ctx.hookState.newInstance);
|
||||
}
|
||||
|
||||
let userFk;
|
||||
if (loopBackContext)
|
||||
|
@ -189,17 +186,16 @@ module.exports = function(Self) {
|
|||
let logModel = definition.settings.log.model;
|
||||
|
||||
let transaction = {};
|
||||
if (ctx.options && ctx.options.transaction) {
|
||||
if (ctx.options && ctx.options.transaction)
|
||||
transaction = ctx.options.transaction;
|
||||
}
|
||||
|
||||
await Self.modelBuilder.models[logModel].create(logsToSave, transaction);
|
||||
await ctx.Model.app.models[logModel].create(logsToSave, transaction);
|
||||
}
|
||||
|
||||
// this function retuns all the instances changed in case this is an updateAll
|
||||
function setLogsToSave(changedInstances, changedInstancesIds, logRecord, ctx) {
|
||||
let promises = [];
|
||||
if (changedInstances && typeof changedInstances == "object") {
|
||||
if (changedInstances && typeof changedInstances == 'object') {
|
||||
for (let i = 0; i < changedInstances.length; i++) {
|
||||
logRecord.changedModelId = changedInstancesIds[i];
|
||||
logRecord.changedModelValue = changedInstances[i];
|
||||
|
@ -207,9 +203,9 @@ module.exports = function(Self) {
|
|||
logRecord.oldInstance = ctx.oldInstances[i];
|
||||
promises.push(JSON.parse(JSON.stringify(logRecord)));
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
return logRecord;
|
||||
}
|
||||
|
||||
return promises;
|
||||
}
|
||||
|
||||
|
@ -217,11 +213,11 @@ module.exports = function(Self) {
|
|||
let oldInstance = ctx.hookState.oldInstance;
|
||||
let newInstance = ctx.hookState.newInstance;
|
||||
|
||||
if (oldInstance && newInstance) {
|
||||
if (oldInstance && newInstance)
|
||||
return 'update';
|
||||
} else if (!oldInstance && newInstance) {
|
||||
else if (!oldInstance && newInstance)
|
||||
return 'insert';
|
||||
}
|
||||
|
||||
return 'delete';
|
||||
}
|
||||
};
|
||||
|
|
|
@ -67,5 +67,6 @@
|
|||
"You can't create a ticket for a inactive client": "No puedes crear un ticket para un cliente inactivo",
|
||||
"Tag value cannot be blank": "El valor del tag no puede quedar en blanco",
|
||||
"ORDER_EMPTY": "Cesta vacía",
|
||||
"You don't have enough privileges to do that": "No tienes permisos para cambiar esto"
|
||||
"You don't have enough privileges to do that": "No tienes permisos para cambiar esto",
|
||||
"You can't create a ticket for a client that has a debt": "No puedes crear un ticket para un client con deuda"
|
||||
}
|
|
@ -40,7 +40,7 @@
|
|||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th number>Id</vn-th>
|
||||
<vn-th number>Item</vn-th>
|
||||
<vn-th>Landed</vn-th>
|
||||
<vn-th number>Quantity</vn-th>
|
||||
<vn-th number>Claimed</vn-th>
|
||||
|
@ -107,7 +107,8 @@
|
|||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th number>Id</vn-th>
|
||||
<vn-th number>Item</vn-th>
|
||||
<vn-th number>Ticket</vn-th>
|
||||
<vn-th>Destination</vn-th>
|
||||
<vn-th number>Landed</vn-th>
|
||||
<vn-th number>Quantity</vn-th>
|
||||
|
@ -126,7 +127,13 @@
|
|||
{{action.sale.itemFk | zeroFill:6}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number>{{action.sale.id}}</vn-td>
|
||||
<vn-td number>
|
||||
<span
|
||||
ng-click="$ctrl.showTicketDescriptor($event, action.sale.ticket.id)"
|
||||
class="link">
|
||||
{{action.sale.ticket.id | zeroFill:6}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td expand>{{action.claimBeggining.description}}</vn-td>
|
||||
<vn-td number>{{action.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}}</vn-td>
|
||||
<vn-td number>{{action.sale.quantity}}</vn-td>
|
||||
|
@ -151,3 +158,6 @@
|
|||
vn-id="workerDescriptor"
|
||||
user-id="$ctrl.selectedWorker">
|
||||
</vn-worker-descriptor-popover>
|
||||
<vn-ticket-descriptor-popover
|
||||
vn-id="ticketDescriptor">
|
||||
</vn-ticket-descriptor-popover>
|
|
@ -33,12 +33,16 @@ class Controller {
|
|||
}
|
||||
|
||||
showWorkerDescriptor(event, userId) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
this.selectedWorker = userId;
|
||||
this.$.workerDescriptor.parent = event.target;
|
||||
this.$.workerDescriptor.show();
|
||||
}
|
||||
|
||||
showTicketDescriptor(event, ticketId) {
|
||||
this.$.ticketDescriptor.ticketFk = ticketId;
|
||||
this.$.ticketDescriptor.parent = event.target;
|
||||
this.$.ticketDescriptor.show();
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', '$http'];
|
||||
|
|
|
@ -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() => {
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
</a>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
<vn-card margin-medium-v>
|
||||
</vn-card>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</div>
|
||||
<a ui-sref="item.create" vn-tooltip="New item" vn-bind="+" fixed-bottom-right>
|
||||
|
|
|
@ -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'));
|
||||
|
||||
|
|
|
@ -3,21 +3,21 @@ const app = require('vn-loopback/server/server');
|
|||
describe('ticket deleted()', () => {
|
||||
let ticket;
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeAll(async() => {
|
||||
let originalTicket = await app.models.Ticket.findOne({where: {id: 16}});
|
||||
originalTicket.id = null;
|
||||
ticket = await app.models.Ticket.create(originalTicket);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
afterAll(async() => {
|
||||
await app.models.Ticket.destroyById(ticket.id);
|
||||
});
|
||||
|
||||
it('should make sure the ticket is not deleted yet', async () => {
|
||||
it('should make sure the ticket is not deleted yet', async() => {
|
||||
expect(ticket.isDeleted).toEqual(false);
|
||||
});
|
||||
|
||||
it('should set a ticket to deleted and log the change on TicketState table', async () => {
|
||||
it('should set a ticket to deleted and log the change on TicketState table', async() => {
|
||||
let ctx = {req: {accessToken: {userId: 9}}};
|
||||
let params = {id: ticket.id};
|
||||
await app.models.Ticket.deleted(ctx, params);
|
||||
|
@ -29,7 +29,7 @@ describe('ticket deleted()', () => {
|
|||
expect(changedState.stateFk).toEqual(17);
|
||||
});
|
||||
|
||||
it('should throw an error if the given ticket has a claim', async () => {
|
||||
it('should throw an error if the given ticket has a claim', async() => {
|
||||
let ctx = {req: {accessToken: {userId: 9}}};
|
||||
let params = {id: 16};
|
||||
let error;
|
||||
|
|
|
@ -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',
|
||||
|
@ -135,27 +135,18 @@ module.exports = Self => {
|
|||
relation: 'user'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
}, {
|
||||
relation: 'atender',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'user'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
relation: 'sale'
|
||||
}
|
||||
]
|
||||
};
|
||||
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);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
{
|
||||
"name": "Ticket",
|
||||
"base": "VnModel",
|
||||
"base": "Loggable",
|
||||
"log": {
|
||||
"model":"TicketLog"
|
||||
},
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "ticket"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
<vn-td number>
|
||||
<span
|
||||
ng-show="::request.saleFk"
|
||||
ng-click="$ctrl.showItemDescriptor($event, request.sale)"
|
||||
ng-click="$ctrl.showItemDescriptor($event, request.sale.itemFk)"
|
||||
class="link">
|
||||
{{request.saleFk | zeroFill:6}}
|
||||
</span>
|
||||
|
|
|
@ -44,18 +44,18 @@ class Controller {
|
|||
});
|
||||
}
|
||||
|
||||
showItemDescriptor(event, sale) {
|
||||
showItemDescriptor(event, itemFk) {
|
||||
this.quicklinks = {
|
||||
btnThree: {
|
||||
icon: 'icon-transaction',
|
||||
state: `item.card.diary({
|
||||
id: ${sale.itemFk},
|
||||
id: ${itemFk},
|
||||
ticketFk: ${this.$stateParams.id}
|
||||
})`,
|
||||
tooltip: 'Item diary'
|
||||
}
|
||||
};
|
||||
this.$.itemDescriptor.itemFk = sale.itemFk;
|
||||
this.$.itemDescriptor.itemFk = itemFk;
|
||||
this.$.itemDescriptor.parent = event.target;
|
||||
this.$.itemDescriptor.show();
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
@ -62,8 +62,8 @@
|
|||
<vn-th shrink></vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
<vn-th number>Id</vn-th>
|
||||
<vn-th>Quantity</vn-th>
|
||||
<vn-th>Item</vn-th>
|
||||
<vn-th number>Quantity</vn-th>
|
||||
<vn-th number>Price</vn-th>
|
||||
<vn-th number>Disc</vn-th>
|
||||
<vn-th number>Amount</vn-th>
|
||||
|
@ -94,7 +94,7 @@
|
|||
icon="icon-reserve"
|
||||
vn-tooltip="{{::$ctrl.$translate.instant('Reserved')}}"></vn-icon>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-td shrink>
|
||||
<img
|
||||
ng-src="{{::$ctrl.imagesPath}}/50x50/{{::sale.image}}"
|
||||
zoom-image="{{::$ctrl.imagesPath}}/1600x900/{{::sale.image}}"
|
||||
|
@ -107,13 +107,6 @@
|
|||
{{::sale.itemFk | zeroFill:6}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td expand>
|
||||
<vn-fetched-tags
|
||||
max-length="6"
|
||||
item="::sale.tags"
|
||||
title="::sale.concept">
|
||||
</vn-fetched-tags>
|
||||
</vn-td>
|
||||
<vn-td ng-if="!$ctrl.isEditable" number>{{sale.quantity}}</vn-td>
|
||||
<vn-td ng-if="$ctrl.isEditable" number>
|
||||
<vn-textfield
|
||||
|
@ -122,22 +115,29 @@
|
|||
type="text">
|
||||
</vn-textfield>
|
||||
</vn-td>
|
||||
<vn-td number
|
||||
ng-if="$ctrl.isEditable"
|
||||
class="link"
|
||||
ng-click="$ctrl.showEditPricePopover($event, sale)"
|
||||
vn-tooltip="Edit price">
|
||||
{{sale.price | currency: 'EUR':2}}
|
||||
<vn-td expand>
|
||||
<vn-fetched-tags
|
||||
max-length="6"
|
||||
item="::sale.tags"
|
||||
title="::sale.concept">
|
||||
</vn-fetched-tags>
|
||||
</vn-td>
|
||||
<vn-td number ng-if="$ctrl.isEditable">
|
||||
<span class="link"
|
||||
vn-tooltip="Edit price"
|
||||
ng-click="$ctrl.showEditPricePopover($event, sale)">
|
||||
{{sale.price | currency: 'EUR':2}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number ng-if="!$ctrl.isEditable">
|
||||
{{sale.price | currency: 'EUR':2}}
|
||||
</vn-td>
|
||||
<vn-td number
|
||||
ng-if="$ctrl.isEditable"
|
||||
class="link"
|
||||
ng-click="$ctrl.showEditPopover($event, sale)"
|
||||
vn-tooltip="Edit discount">
|
||||
{{sale.discount}} %
|
||||
<vn-td number ng-if="$ctrl.isEditable">
|
||||
<span class="link"
|
||||
vn-tooltip="Edit discount"
|
||||
ng-click="$ctrl.showEditPopover($event, sale)">
|
||||
{{sale.discount}} %
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number
|
||||
ng-if="!$ctrl.isEditable">
|
||||
|
@ -158,7 +158,7 @@
|
|||
<!-- Edit Price Popover -->
|
||||
<vn-popover
|
||||
class="edit dialog-summary"
|
||||
vn-id="editPricePopover"
|
||||
vn-id="edit-price-popover"
|
||||
on-open="$ctrl.getManaSalespersonMana()">
|
||||
<vn-horizontal pad-medium class="header">
|
||||
<h5>MANÁ: {{$ctrl.mana | currency: 'EUR':0}}</h5>
|
||||
|
@ -185,7 +185,7 @@
|
|||
<!-- Edit Popover -->
|
||||
<vn-popover
|
||||
class="edit dialog-summary"
|
||||
vn-id="editPopover"
|
||||
vn-id="edit-popover"
|
||||
on-open="$ctrl.getManaSalespersonMana()">
|
||||
<vn-ticket-sale-edit-discount
|
||||
mana="$ctrl.mana"
|
||||
|
|
|
@ -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">
|
||||
|
@ -57,8 +57,8 @@
|
|||
<vn-tr>
|
||||
<vn-th shrink></vn-th>
|
||||
<vn-th number>Item</vn-th>
|
||||
<vn-th>Description</vn-th>
|
||||
<vn-th number>Quantity</vn-th>
|
||||
<vn-th>Description</vn-th>
|
||||
<vn-th number>Price</vn-th>
|
||||
<vn-th number>Discount</vn-th>
|
||||
<vn-th number>Amount</vn-th>
|
||||
|
@ -89,8 +89,8 @@
|
|||
{{sale.itemFk | zeroFill:6}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td expand><vn-fetched-tags max-length="6" item="sale.item" title="sale.concept"/></vn-td>
|
||||
<vn-td number>{{::sale.quantity}}</vn-td>
|
||||
<vn-td expand><vn-fetched-tags max-length="6" item="sale.item" title="sale.concept"/></vn-td>
|
||||
<vn-td number>{{::sale.price | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{::sale.discount}} %</vn-td>
|
||||
<vn-td number>{{::sale.quantity * sale.price | currency: 'EUR':2}}</vn-td>
|
||||
|
@ -123,8 +123,8 @@
|
|||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th number>Id</vn-th>
|
||||
<vn-th>Description</vn-th>
|
||||
<vn-th number>Quantity</vn-th>
|
||||
<vn-th>Description</vn-th>
|
||||
<vn-th number>Price</vn-th>
|
||||
<vn-th>Tax class</vn-th>
|
||||
</vn-tr>
|
||||
|
@ -132,8 +132,8 @@
|
|||
<vn-tbody>
|
||||
<vn-tr ng-repeat="service in $ctrl.summary.services">
|
||||
<vn-td number>{{::service.id}}</vn-td>
|
||||
<vn-td expand>{{::service.description}}</vn-td>
|
||||
<vn-td number>{{::service.quantity}}</vn-td>
|
||||
<vn-td expand>{{::service.description}}</vn-td>
|
||||
<vn-td number>{{::service.price}}</vn-td>
|
||||
<vn-td>{{::service.taxClass.description}}</vn-td>
|
||||
</vn-tr>
|
||||
|
@ -151,7 +151,7 @@
|
|||
<vn-th>Atender</vn-th>
|
||||
<vn-th number>Quantity</vn-th>
|
||||
<vn-th number>Price</vn-th>
|
||||
<vn-th number>Sale id</vn-th>
|
||||
<vn-th number>Item</vn-th>
|
||||
<vn-th number>Ok</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
|
@ -166,9 +166,9 @@
|
|||
<vn-td number>
|
||||
<span
|
||||
ng-show="::request.saleFk"
|
||||
ng-click="$ctrl.showDescriptor($event, request.saleFk)"
|
||||
ng-click="$ctrl.showDescriptor($event, request.sale.itemFk)"
|
||||
class="link">
|
||||
{{request.saleFk | zeroFill:6}}
|
||||
{{request.sale.itemFk | zeroFill:6}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number>
|
||||
|
|
|
@ -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