Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 3430-ticket_step-two
gitea/salix/pipeline/head There was a failure building this commit Details

This commit is contained in:
Alex Moreno 2021-12-20 13:50:50 +01:00
commit 50db693e51
58 changed files with 1628 additions and 617 deletions

View File

@ -618,8 +618,10 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF
(21, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Holland', 102, NULL, 0, 13, 5, 1, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(22, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 1109, 'Somewhere in Japan', 103, NULL, 0, 13, 5, 1, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(23, NULL, 8, 1, 7, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 1101, 'address 21', 121, NULL, 0, 5, 5, 1, CURDATE()),
(24 ,NULL, 8, 1, 7, CURDATE(), CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 5, 5, 1, CURDATE());
(24 ,NULL, 8, 1, 7, CURDATE(), CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 5, 5, 1, CURDATE()),
(25 ,NULL, 8, 1, NULL, CURDATE(), CURDATE(), 1101, 'Bruce Wayne', 1, NULL, 0, 1, 5, 1, CURDATE()),
(26 ,NULL, 8, 1, NULL, CURDATE(), CURDATE(), 1101, 'An incredibly long alias for testing purposes', 1, NULL, 0, 1, 5, 1, CURDATE()),
(27 ,NULL, 8, 1, NULL, CURDATE(), CURDATE(), 1101, 'Wolverine', 1, NULL, 0, 1, 5, 1, CURDATE());
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
VALUES
(1, 11, 1, 'ready'),

View File

@ -127,8 +127,8 @@ describe('Item regularize path', () => {
await page.waitForState('ticket.index');
});
it('should search for the ticket with id 25 once again', async() => {
await page.accessToSearchResult('25');
it('should search for the ticket with id 28 once again', async() => {
await page.accessToSearchResult('28');
await page.waitForState('ticket.card.summary');
});

View File

@ -33,7 +33,7 @@ describe('Ticket index payout path', () => {
await page.waitToClick(selectors.ticketsIndex.openAdvancedSearchButton);
await page.write(selectors.ticketsIndex.advancedSearchClient, '1101');
await page.keyboard.press('Enter');
await page.waitForNumberOfElements(selectors.ticketsIndex.anySearchResult, 6);
await page.waitForNumberOfElements(selectors.ticketsIndex.anySearchResult, 9);
await page.waitToClick(selectors.ticketsIndex.firstTicketCheckbox);
await page.waitToClick(selectors.ticketsIndex.secondTicketCheckbox);

View File

@ -52,8 +52,6 @@
"Agency cannot be blank": "La agencia no puede quedar en blanco",
"You can't make changes on a client with verified data": "No puedes hacer cambios en un cliente con datos comprobados",
"This address doesn't exist": "Este consignatario no existe",
"You can't create an order for a inactive client": "You can't create an order for a inactive client",
"You can't create an order for a client that doesn't has tax data verified": "You can't create an order for a client that doesn't has tax data verified",
"You must delete the claim id %d first": "Antes debes borrar la reclamación %d",
"You don't have enough privileges": "No tienes suficientes permisos",
"Cannot check Equalization Tax in this NIF/CIF": "No se puede marcar RE en este NIF/CIF",

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
describe('entry addBuy()', () => {
@ -25,11 +25,11 @@ describe('entry addBuy()', () => {
packageFk: 3
};
const tx = await app.models.Entry.beginTransaction({});
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const newBuy = await app.models.Entry.addBuy(ctx, options);
const newBuy = await models.Entry.addBuy(ctx, options);
expect(newBuy.itemFk).toEqual(itemId);

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
describe('sale deleteBuys()', () => {
@ -15,13 +15,13 @@ describe('sale deleteBuys()', () => {
active: activeCtx
});
const tx = await app.models.Entry.beginTransaction({});
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
ctx.args = {buys: [{id: 1}]};
try {
const result = await app.models.Buy.deleteBuys(ctx, options);
const result = await models.Buy.deleteBuys(ctx, options);
expect(result).toEqual([{count: 1}]);
await tx.rollback();

View File

@ -1,9 +1,8 @@
const app = require('vn-loopback/server/server');
const model = app.models.Buy;
const models = require('vn-loopback/server/server').models;
describe('Buy editLatestsBuys()', () => {
it('should change the value of a given column for the selected buys', async() => {
const tx = await app.models.Entry.beginTransaction({});
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
@ -13,15 +12,15 @@ describe('Buy editLatestsBuys()', () => {
}
};
const [original] = await model.latestBuysFilter(ctx, null, options);
const [original] = await models.Buy.latestBuysFilter(ctx, null, options);
const field = 'size';
const newValue = 99;
const lines = [{itemFk: original.itemFk, id: original.id}];
await model.editLatestBuys(field, newValue, lines, options);
await models.Buy.editLatestBuys(field, newValue, lines, options);
const [result] = await model.latestBuysFilter(ctx, null, options);
const [result] = await models.Buy.latestBuysFilter(ctx, null, options);
expect(result[field]).toEqual(newValue);

View File

@ -1,77 +1,137 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('Entry filter()', () => {
it('should return the entry matching "search"', async() => {
let ctx = {
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
search: 1
}
};
let result = await app.models.Entry.filter(ctx);
const result = await models.Entry.filter(ctx, 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 the entry matching the currency', async() => {
let ctx = {
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
currencyFk: 1
}
};
let result = await app.models.Entry.filter(ctx);
const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(8);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the entry matching the supplier', async() => {
let ctx = {
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
supplierFk: 2
}
};
let result = await app.models.Entry.filter(ctx);
const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(6);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the entry matching the company', async() => {
let ctx = {
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
companyFk: 442
}
};
let result = await app.models.Entry.filter(ctx);
const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(7);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the entries matching isBooked', async() => {
let ctx = {
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
isBooked: true,
}
};
let result = await app.models.Entry.filter(ctx);
const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the routes matching the reference and travel', async() => {
let ctx = {
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
reference: 'movement',
travelFk: '2'
}
};
let result = await app.models.Entry.filter(ctx);
const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,14 +1,24 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('entry getBuys()', () => {
const entryId = 4;
it('should get the buys and items of an entry', async() => {
const result = await app.models.Entry.getBuys(entryId);
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const result = await models.Entry.getBuys(entryId, options);
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
expect(result.length).toEqual(4);
expect(anyResult.item).toBeDefined();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,31 +1,71 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('travel getEntry()', () => {
const entryId = 1;
it('should check the entry contains the id', async() => {
const entry = await app.models.Entry.getEntry(entryId);
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const entry = await models.Entry.getEntry(entryId, options);
expect(entry.id).toEqual(entryId);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should check the entry contains the supplier name', async() => {
const entry = await app.models.Entry.getEntry(entryId);
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const entry = await models.Entry.getEntry(entryId, options);
const supplierName = entry.supplier().nickname;
expect(supplierName).toEqual('Plants nick');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should check the entry contains the receiver warehouse name', async() => {
const entry = await app.models.Entry.getEntry(entryId);
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const entry = await models.Entry.getEntry(entryId, options);
const receiverWarehouseName = entry.travel().warehouseIn().name;
expect(receiverWarehouseName).toEqual('Warehouse One');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should check the entry contains the company code', async() => {
const entry = await app.models.Entry.getEntry(entryId);
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const entry = await models.Entry.getEntry(entryId, options);
const companyCode = entry.company().code;
expect(companyCode).toEqual('VNL');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
describe('entry import()', () => {
@ -48,10 +48,10 @@ describe('entry import()', () => {
]
}
};
const tx = await app.models.Entry.beginTransaction({});
const tx = await models.Entry.beginTransaction({});
try {
const options = {transaction: tx};
const newEntry = await app.models.Entry.create({
const newEntry = await models.Entry.create({
dated: new Date(),
supplierFk: supplierId,
travelFk: travelId,
@ -60,10 +60,10 @@ describe('entry import()', () => {
ref: 'Entry ref'
}, options);
await app.models.Entry.importBuys(ctx, newEntry.id, options);
await models.Entry.importBuys(ctx, newEntry.id, options);
const updatedEntry = await app.models.Entry.findById(newEntry.id, null, options);
const entryBuys = await app.models.Buy.find({
const updatedEntry = await models.Entry.findById(newEntry.id, null, options);
const entryBuys = await models.Buy.find({
where: {entryFk: newEntry.id}
}, options);

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
describe('entry importBuysPreview()', () => {
@ -10,6 +10,10 @@ describe('entry importBuysPreview()', () => {
});
it('should return the buys with the calculated packageFk', async() => {
const tx = await models.Entry.beginTransaction({});
const options = {transaction: tx};
try {
const expectedPackageFk = '3';
const buys = [
{
@ -30,10 +34,16 @@ describe('entry importBuysPreview()', () => {
}
];
const result = await app.models.Entry.importBuysPreview(entryId, buys);
const result = await models.Entry.importBuysPreview(entryId, buys, options);
const randomIndex = Math.floor(Math.random() * result.length);
const buy = result[randomIndex];
expect(buy.packageFk).toEqual(expectedPackageFk);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,34 +1,58 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('Buy latests buys filter()', () => {
it('should return the entry matching "search"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
search: 'Ranged weapon longbow 2m'
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
let firstBuy = results[0];
const results = await models.Buy.latestBuysFilter(ctx);
const firstBuy = results[0];
expect(results.length).toEqual(1);
expect(firstBuy.size).toEqual(70);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the entry matching "id"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
id: 1
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "tags"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
tags: [
{tagFk: 27, value: '2m'}
@ -36,160 +60,286 @@ describe('Buy latests buys filter()', () => {
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "categoryFk"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
categoryFk: 1
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "typeFk"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
typeFk: 2
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "active"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
active: true
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(6);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "not active"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
active: false
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "visible"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
visible: true
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(5);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "not visible"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
visible: false
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "floramondo"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
floramondo: true
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "not floramondo"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
floramondo: false
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(5);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "salesPersonFk"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
salesPersonFk: 35
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(6);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "description"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
description: 'Increases block'
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "supplierFk"', async() => {
let ctx = {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {
args: {
supplierFk: 1
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "from" and "to"', async() => {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const from = new Date();
from.setHours(0, 0, 0, 0);
const to = new Date();
to.setHours(23, 59, 59, 999);
let ctx = {
const ctx = {
args: {
from: from,
to: to
}
};
let results = await app.models.Buy.latestBuysFilter(ctx);
const results = await models.Buy.latestBuysFilter(ctx, options);
expect(results.length).toBe(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -11,7 +11,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {order: 'id DESC'};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
expect(result.length).toEqual(24);
expect(result.length).toEqual(27);
await tx.rollback();
} catch (e) {
@ -39,7 +39,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
expect(result.length).toEqual(13);
expect(result.length).toEqual(16);
await tx.rollback();
} catch (e) {
@ -87,7 +87,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
expect(result.length).toEqual(24);
expect(result.length).toEqual(27);
await tx.rollback();
} catch (e) {
@ -130,7 +130,7 @@ describe('SalesMonitor salesFilter()', () => {
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
expect(length).toEqual(7);
expect(length).toEqual(10);
expect(anyResult.state).toMatch(/(Libre|Arreglar)/);
await tx.rollback();
@ -175,7 +175,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
expect(result.length).toEqual(20);
expect(result.length).toEqual(23);
await tx.rollback();
} catch (e) {

View File

@ -21,22 +21,42 @@ module.exports = Self => {
}
});
Self.addToOrder = async params => {
let isEditable = await Self.app.models.Order.isEditable(params.orderFk);
Self.addToOrder = async(params, options) => {
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const isEditable = await Self.app.models.Order.isEditable(params.orderFk, myOptions);
if (!isEditable)
throw new UserError('This order is not editable');
let promises = [];
params.items.forEach(item => {
const promises = [];
for (const item of params.items) {
promises.push(
Self.rawSql(
`CALL hedera.order_addItem(?, ?, ?, ?)`,
[params.orderFk, item.warehouseFk, item.itemFk, item.quantity]
[params.orderFk, item.warehouseFk, item.itemFk, item.quantity],
myOptions
)
);
});
}
await Promise.all(promises);
if (tx) await tx.commit();
return true;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -21,19 +21,39 @@ module.exports = Self => {
}
});
Self.removes = async params => {
Self.removes = async(params, options) => {
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
if (!params.rows || !params.rows.length)
throw new UserError('There is nothing to delete');
let isEditable = await Self.app.models.Order.isEditable(params.actualOrderId);
const isEditable = await Self.app.models.Order.isEditable(params.actualOrderId, myOptions);
if (!isEditable)
throw new UserError('This order is not editable');
let promises = [];
const promises = [];
for (let i = 0; i < params.rows.length; i++)
promises.push(Self.app.models.OrderRow.destroyById(params.rows[i]));
promises.push(Self.app.models.OrderRow.destroyById(params.rows[i], myOptions));
return await Promise.all(promises);
const deletions = await Promise.all(promises);
if (tx) await tx.commit();
return deletions;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -1,18 +1,18 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order addToOrder()', () => {
const orderId = 8;
let rowToDelete;
afterAll(async() => {
await app.models.OrderRow.removes({rows: [rowToDelete], actualOrderId: orderId});
});
it('should add a row to a given order', async() => {
let unmodifiedRows = await app.models.OrderRow.find({where: {orderFk: orderId}});
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const unmodifiedRows = await models.OrderRow.find({where: {orderFk: orderId}}, options);
expect(unmodifiedRows.length).toBe(2);
let params = {
const params = {
orderFk: orderId,
items: [{
itemFk: 1,
@ -21,12 +21,16 @@ describe('order addToOrder()', () => {
}]
};
await app.models.OrderRow.addToOrder(params);
await models.OrderRow.addToOrder(params, options);
let modifiedRows = await app.models.OrderRow.find({where: {orderFk: orderId}});
rowToDelete = modifiedRows[modifiedRows.length - 1].id;
const modifiedRows = await models.OrderRow.find({where: {orderFk: orderId}}, options);
expect(modifiedRows.length).toBe(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,20 +1,18 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order removes()', () => {
let row;
let newRow;
beforeAll(async() => {
row = await app.models.OrderRow.findOne({where: {id: 12}});
row.id = null;
newRow = await app.models.OrderRow.create(row);
});
it('should throw an error if rows property is empty', async() => {
const tx = await models.Order.beginTransaction({});
let error;
try {
await app.models.OrderRow.removes({rows: []});
const options = {transaction: tx};
await models.OrderRow.removes({rows: []}, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
@ -22,10 +20,17 @@ describe('order removes()', () => {
});
it('should throw an error if the row selected is not editable', async() => {
const tx = await models.Order.beginTransaction({});
let error;
try {
await app.models.OrderRow.removes({rows: [2]});
const options = {transaction: tx};
await models.OrderRow.removes({rows: [2]}, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
@ -33,13 +38,24 @@ describe('order removes()', () => {
});
it('should delete the row', async() => {
let params = {
rows: [newRow.id],
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const params = {
rows: [12],
actualOrderId: 16
};
let res = await app.models.OrderRow.removes(params);
const res = await models.OrderRow.removes(params, options);
expect(res).toEqual([{count: 1}]);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -7,28 +7,28 @@ module.exports = Self => {
accepts: [
{
arg: 'orderFk',
type: 'Number',
type: 'number',
required: true
},
{
arg: 'orderBy',
type: 'Object',
type: 'object',
description: 'Items order',
required: true
},
{
arg: 'filter',
type: 'Object',
type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string'
},
{
arg: 'tagGroups',
type: ['Object'],
type: ['object'],
description: 'Filter by tag'
},
],
returns: {
type: ['Object'],
type: ['object'],
root: true,
},
http: {
@ -37,8 +37,13 @@ module.exports = Self => {
},
});
Self.catalogFilter = async(orderFk, orderBy, filter, tagGroups) => {
let conn = Self.dataSource.connector;
Self.catalogFilter = async(orderFk, orderBy, filter, tagGroups, options) => {
const conn = Self.dataSource.connector;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const stmts = [];
let stmt;
@ -85,7 +90,7 @@ module.exports = Self => {
stmts.push(stmt);
// Calculate items
const order = await Self.findById(orderFk);
const order = await Self.findById(orderFk, null, myOptions);
stmts.push(new ParameterizedSQL(
'CALL vn.catalog_calculate(?, ?, ?)', [
order.landed,
@ -131,9 +136,9 @@ module.exports = Self => {
params: [orderBy.field],
});
let way = orderBy.way == 'DESC' ? 'DESC' : 'ASC';
let tag = await Self.app.models.Tag.findById(orderBy.field);
let orderSql = `
const way = orderBy.way == 'DESC' ? 'DESC' : 'ASC';
const tag = await Self.app.models.Tag.findById(orderBy.field, null, myOptions);
const orderSql = `
ORDER BY
itg.value IS NULL,
${tag.isQuantitative ? 'CAST(itg.value AS SIGNED)' : 'itg.value'}
@ -181,7 +186,7 @@ module.exports = Self => {
stmts.push('CALL vn.ticketCalculatePurge()');
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql);
const result = await conn.executeStmt(sql, myOptions);
// Add prices to items
result[itemsIndex].forEach(item => {

View File

@ -21,7 +21,10 @@ module.exports = Self => {
Self.confirm = async(ctx, orderFk) => {
const userId = ctx.req.accessToken.userId;
let query = `CALL hedera.order_confirmWithUser(?, ?)`;
return await Self.rawSql(query, [orderFk, userId]);
const query = `CALL hedera.order_confirmWithUser(?, ?)`;
const response = await Self.rawSql(query, [orderFk, userId]);
return response;
};
};

View File

@ -9,60 +9,60 @@ module.exports = Self => {
accepts: [
{
arg: 'ctx',
type: 'Object',
type: 'object',
http: {source: 'context'}
}, {
arg: 'filter',
type: 'Object',
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string'
}, {
arg: 'search',
type: 'String',
type: 'string',
description: `If it's and integer searchs by id, otherwise it searchs by nickname`
}, {
arg: 'from',
type: 'Date',
description: `The from date`
type: 'date',
description: 'The from date'
}, {
arg: 'to',
type: 'Date',
description: `The to date`
type: 'date',
description: 'The to date'
}, {
arg: 'id',
type: 'Integer',
description: `The ticket id`
type: 'integer',
description: 'The ticket id'
}, {
arg: 'clientFk',
type: 'Integer',
description: `The client id`
type: 'integer',
description: 'The client id'
}, {
arg: 'ticketFk',
type: 'Integer',
description: `The ticket id`
type: 'integer',
description: 'The ticket id'
}, {
arg: 'agencyModeFk',
type: 'Integer',
description: `The agency mode id`
type: 'integer',
description: 'The agency mode id'
}, {
arg: 'workerFk',
type: 'Integer',
description: `The salesperson id`
type: 'integer',
description: 'The salesperson id'
}, {
arg: 'myTeam',
type: 'Boolean',
description: `Whether to show only tickets for the current logged user team (For now it shows only the current user tickets)`
type: 'boolean',
description: 'Whether to show only tickets for the current logged user team (currently user tickets)'
}, {
arg: 'isConfirmed',
type: 'Boolean',
description: `Order is confirmed`
type: 'boolean',
description: 'Order is confirmed'
}, {
arg: 'showEmpty',
type: 'boolean',
description: `Show empty orders`
description: 'Show empty orders'
}
],
returns: {
type: ['Object'],
type: ['object'],
root: true
},
http: {
@ -71,34 +71,35 @@ module.exports = Self => {
}
});
Self.filter = async(ctx, filter) => {
let conn = Self.dataSource.connector;
let worker = await Self.app.models.Worker.findOne({
where: {userFk: ctx.req.accessToken.userId},
include: [
{relation: 'collegues'}
]
});
Self.filter = async(ctx, filter, options) => {
const conn = Self.dataSource.connector;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const args = ctx.args;
let teamIds = [];
if (worker.collegues().length && args.myTeam) {
worker.collegues().forEach(collegue => {
teamIds.push(collegue.collegueFk);
});
// Apply filter by team
const teamMembersId = [];
if (args.myTeam != null) {
const worker = await models.Worker.findById(userId, {
include: {
relation: 'collegues'
}
}, myOptions);
const collegues = worker.collegues() || [];
for (let collegue of collegues)
teamMembersId.push(collegue.collegueFk);
if (worker.collegues().length === 0 && args.myTeam) {
worker = await Self.app.models.Worker.findOne({
fields: ['id'],
where: {userFk: ctx.req.accessToken.userId}
});
teamIds = [worker && worker.id];
if (teamMembersId.length == 0)
teamMembersId.push(userId);
}
if (args && args.myTeam)
args.teamIds = teamIds;
let where = buildFilter(args, (param, value) => {
const where = buildFilter(args, (param, value) => {
switch (param) {
case 'search':
return /^\d+$/.test(value)
@ -123,7 +124,10 @@ module.exports = Self => {
case 'isConfirmed':
return {'o.confirmed': value ? 1 : 0};
case 'myTeam':
return {'c.salesPersonFk': {inq: teamIds}};
if (value)
return {'c.salesPersonFk': {inq: teamMembersId}};
else
return {'c.salesPersonFk': {nin: teamMembersId}};
case 'showEmpty':
return {'o.total': {neq: value}};
case 'id':
@ -133,7 +137,7 @@ module.exports = Self => {
});
filter = mergeFilters(filter, {where});
let stmts = [];
const stmts = [];
let stmt;
stmt = new ParameterizedSQL(
@ -183,7 +187,7 @@ module.exports = Self => {
stmts.push(`DROP TEMPORARY TABLE tmp.filter`);
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql);
const result = await conn.executeStmt(sql, myOptions);
return result[ordersIndex];
};

View File

@ -3,7 +3,7 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
module.exports = Self => {
Self.remoteMethod('getItemTypeAvailable', {
description: 'Gets the item types available for an rder and item category ',
description: 'Gets the item types available for an order and item category',
accessType: 'READ',
accepts: [{
arg: 'id',
@ -27,11 +27,16 @@ module.exports = Self => {
}
});
Self.getItemTypeAvailable = async(orderId, itemCategoryId) => {
Self.getItemTypeAvailable = async(orderId, itemCategoryId, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const stmts = [];
let stmt;
const order = await app.models.Order.findById(orderId);
const order = await app.models.Order.findById(orderId, null, myOptions);
stmt = new ParameterizedSQL('call vn.available_calc(?, ?, ?)', [
order.landed,
order.addressFk,
@ -78,7 +83,7 @@ module.exports = Self => {
stmts.push('DROP TEMPORARY TABLE tmp.item');
const sql = ParameterizedSQL.join(stmts, ';');
const result = await Self.rawStmt(sql);
const result = await Self.rawStmt(sql, myOptions);
return result[categoriesIndex];
};

View File

@ -3,7 +3,7 @@ module.exports = Self => {
description: 'Gets the sourceApp type set',
accessType: 'READ',
returns: {
type: ['String'],
type: ['string'],
root: true
},
http: {

View File

@ -21,10 +21,14 @@ module.exports = Self => {
}
});
Self.getTaxes = async orderFk => {
let conn = Self.dataSource.connector;
let stmts = [];
Self.getTaxes = async(orderFk, options) => {
const conn = Self.dataSource.connector;
const stmts = [];
let stmt;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.order');
@ -37,15 +41,15 @@ module.exports = Self => {
stmts.push('CALL hedera.order_getTax()');
let orderTaxIndex = stmts.push('SELECT * FROM tmp.orderAmount') - 1;
const orderTaxIndex = stmts.push('SELECT * FROM tmp.orderAmount') - 1;
stmts.push(`
DROP TEMPORARY TABLE
tmp.order,
tmp.orderTax`);
let sql = ParameterizedSQL.join(stmts, ';');
let result = await conn.executeStmt(sql);
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql, myOptions);
return result[orderTaxIndex];
};

View File

@ -19,9 +19,14 @@ module.exports = Self => {
}
});
Self.getTotal = async orderFk => {
let query = `SELECT hedera.order_getTotal(?) total;`;
let [total] = await Self.rawSql(query, [orderFk]);
Self.getTotal = async(orderFk, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = `SELECT hedera.order_getTotal(?) total;`;
const [total] = await Self.rawSql(query, [orderFk], myOptions);
return total.total;
};

View File

@ -19,9 +19,14 @@ module.exports = Self => {
}
});
Self.getTotalVolume = async orderFk => {
let query = `SELECT vn.orderTotalVolume(?) totalVolume, vn.orderTotalVolumeBoxes(?) totalBoxes`;
let [res] = await Self.rawSql(query, [orderFk, orderFk]);
Self.getTotalVolume = async(orderFk, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = `SELECT vn.orderTotalVolume(?) totalVolume, vn.orderTotalVolumeBoxes(?) totalBoxes`;
const [res] = await Self.rawSql(query, [orderFk, orderFk], myOptions);
return res;
};
};

View File

@ -19,9 +19,14 @@ module.exports = Self => {
}
});
Self.getVAT = async orderId => {
Self.getVAT = async(orderId, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
let totalTax = 0.00;
let taxes = await Self.app.models.Order.getTaxes(orderId);
const taxes = await Self.app.models.Order.getTaxes(orderId, myOptions);
taxes.forEach(tax => {
totalTax += tax.tax;
});

View File

@ -18,8 +18,13 @@ module.exports = Self => {
}
});
Self.getVolumes = async orderFk => {
let [volume] = await Self.rawSql(`CALL vn.orderListVolume(?)`, [orderFk]);
Self.getVolumes = async(orderFk, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const [volume] = await Self.rawSql(`CALL vn.orderListVolume(?)`, [orderFk], myOptions);
return volume;
};
};

View File

@ -19,8 +19,13 @@ module.exports = Self => {
}
});
Self.isEditable = async orderId => {
let exists = await Self.app.models.Order.findOne({
Self.isEditable = async(orderId, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const exists = await Self.app.models.Order.findOne({
where: {id: orderId},
fields: ['isConfirmed', 'clientFk'],
include: [
@ -32,7 +37,7 @@ module.exports = Self => {
}
}
]
});
}, myOptions);
if (exists && exists.client().type().code !== 'normal')
return true;

View File

@ -32,8 +32,20 @@ module.exports = Self => {
}
});
Self.new = async(landed, addressId, agencyModeId) => {
let address = await Self.app.models.Address.findOne({
Self.new = async(landed, addressId, agencyModeId, options) => {
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const address = await Self.app.models.Address.findOne({
where: {id: addressId},
fields: ['clientFk'],
include: [
@ -45,11 +57,11 @@ module.exports = Self => {
}
}
]
});
}, myOptions);
if (address.client().type().code === 'normal') {
if (!address.client().isActive)
throw new UserError(`You can't create an order for a inactive client`);
throw new UserError(`You can't create an order for an inactive client`);
}
query = `CALL vn.orderListCreate(?, ?, ?, ?);`;
@ -58,8 +70,14 @@ module.exports = Self => {
agencyModeId,
addressId,
'SALIX'
]);
], myOptions);
if (tx) await tx.commit();
return result[0].vOrderId;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -18,17 +18,35 @@ module.exports = Self => {
}
});
Self.newFromTicket = async ticketFk => {
let ticket = await Self.app.models.Ticket.findOne({
Self.newFromTicket = async(ticketFk, options) => {
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const ticket = await Self.app.models.Ticket.findOne({
where: {id: ticketFk}
});
}, myOptions);
let landed = ticket.landed;
let addressFk = ticket.addressFk;
let agencyModeFk = ticket.agencyModeFk;
const landed = ticket.landed;
const addressFk = ticket.addressFk;
const agencyModeFk = ticket.agencyModeFk;
let orderID = await Self.app.models.Order.new(landed, addressFk, agencyModeFk);
const orderID = await Self.app.models.Order.new(landed, addressFk, agencyModeFk, myOptions);
if (tx) await tx.commit();
return orderID;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -1,27 +1,43 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order catalogFilter()', () => {
const colorTagId = 1;
const categoryTagId = 67;
it('should return an array of items', async() => {
let filter = {
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {
where: {
categoryFk: 1,
typeFk: 2
}
};
let tags = [];
let orderFk = 11;
let orderBy = {field: 'relevancy DESC, name', way: 'DESC'};
let result = await app.models.Order.catalogFilter(orderFk, orderBy, filter, tags);
let firstItemId = result[0].id;
const tags = [];
const orderFk = 11;
const orderBy = {field: 'relevancy DESC, name', way: 'DESC'};
const result = await models.Order.catalogFilter(orderFk, orderBy, filter, tags, options);
const firstItemId = result[0].id;
expect(result.length).toEqual(4);
expect(firstItemId).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should now return an array of items based on tag filter', async() => {
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {
where: {
categoryFk: 1,
@ -35,7 +51,7 @@ describe('order catalogFilter()', () => {
];
const orderFk = 11;
const orderBy = {field: 'relevancy DESC, name', way: 'DESC'};
const result = await app.models.Order.catalogFilter(orderFk, orderBy, filter, tagGroups);
const result = await models.Order.catalogFilter(orderFk, orderBy, filter, tagGroups, options);
const randomIndex = Math.round(Math.random());
const item = result[randomIndex];
@ -47,5 +63,11 @@ describe('order catalogFilter()', () => {
expect(result.length).toEqual(2);
expect(colorTag.value).toEqual('Silver');
expect(categoryTag.value).toEqual('Concussion');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order filter()', () => {
const ctx = {
@ -8,51 +8,107 @@ describe('order filter()', () => {
};
it('should call the filter method with a basic search', async() => {
const myCtx = Object.assign({}, ctx);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {where: {'o.id': 2}};
const result = await app.models.Order.filter(ctx, filter);
const result = await models.Order.filter(myCtx, filter, options);
const orderId = result[0].id;
expect(orderId).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should call the filter method with a single advanced search', async() => {
const myCtx = Object.assign({}, ctx);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {where: {'o.confirmed': false}};
const result = await app.models.Order.filter(ctx, filter);
const result = await models.Order.filter(myCtx, filter, options);
expect(result.length).toEqual(16);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should call the filter method with a complex advanced search', async() => {
const myCtx = Object.assign({}, ctx);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {where: {'o.confirmed': false, 'c.salesPersonFk': 18}};
const result = await app.models.Order.filter(ctx, filter);
const result = await models.Order.filter(myCtx, filter, options);
expect(result.length).toEqual(9);
expect(result[0].id).toEqual(7);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the orders matching the showEmpty on false', async() => {
const myCtx = Object.assign({}, ctx);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {};
ctx.args = {showEmpty: false};
const result = await app.models.Order.filter(ctx, filter);
myCtx.args = {showEmpty: false};
const result = await models.Order.filter(myCtx, filter, options);
const hasEmptyLines = result.some(order => {
return order.total === 0;
});
expect(hasEmptyLines).toBeFalsy();
ctx.args = {showEmpty: null};
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the orders matching the showEmpty on true', async() => {
const myCtx = Object.assign({}, ctx);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {};
ctx.args = {showEmpty: true};
const result = await app.models.Order.filter(ctx, filter);
myCtx.args = {showEmpty: true};
const result = await models.Order.filter(myCtx, filter, options);
const hasEmptyLines = result.some(order => {
return order.total === 0;
});
expect(hasEmptyLines).toBeTruthy();
ctx.args = {showEmpty: null};
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,19 +1,41 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order getItemTypeAvailable()', () => {
it('should call the getItemTypeAvailable method with a valid order and item category', async() => {
let orderId = 11;
let itemCategoryId = 1;
let result = await app.models.Order.getItemTypeAvailable(orderId, itemCategoryId);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const orderId = 11;
const itemCategoryId = 1;
const result = await models.Order.getItemTypeAvailable(orderId, itemCategoryId, options);
expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should call the getItemTypeAvailable method with the same order and different item category', async() => {
let orderId = 11;
let itemCategoryId = 4;//
let result = await app.models.Order.getItemTypeAvailable(orderId, itemCategoryId);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const orderId = 11;
const itemCategoryId = 4;
const result = await models.Order.getItemTypeAvailable(orderId, itemCategoryId, options);
expect(result.length).toEqual(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,31 +1,75 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order getTaxes()', () => {
it('should call the getTaxes method and return undefined if its called with a string', async() => {
let result = await app.models.Order.getTaxes('string');
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.getTaxes('string', options);
expect(result.length).toEqual(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should call the getTaxes method and return undefined if its called with unknown id', async() => {
let result = await app.models.Order.getTaxes(99999999999999999999999);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.getTaxes(9999, options);
expect(result.length).toEqual(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should call the getTaxes method and return the taxes splited if different type of taxes', async() => {
let result = await app.models.Order.getTaxes(1);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.getTaxes(1, options);
const expectedResult = result[0].tax + result[1].tax;
expect(expectedResult).toEqual(20.29);
expect(result.length).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should call the getTaxes method and return the taxes for them same type', async() => {
let result = await app.models.Order.getTaxes(2);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.getTaxes(2, options);
expect(result[0].tax).toEqual(9.1);
expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,9 +1,19 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order getTotal()', () => {
it('should return the order total', async() => {
let result = await app.models.Order.getTotal(1);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.getTotal(1, options);
expect(result).toEqual(155.89);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,10 +1,21 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order getTotalVolume()', () => {
it('should return the total', async() => {
let result = await app.models.Order.getTotalVolume(1);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.getTotalVolume(1, options);
expect(result.totalVolume).toEqual(1.568);
expect(result.totalBoxes).toEqual(11.1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,9 +1,20 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order getVAT()', () => {
it('should return the order VAT', async() => {
const result = await app.models.Order.getVAT(1);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.getVAT(1, options);
expect(result).toEqual(20.29);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,9 +1,20 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order getVolumes()', () => {
it('should return the volumes of a given order id', async() => {
let [result] = await app.models.Order.getVolumes(1);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const [result] = await models.Order.getVolumes(1, options);
expect(result.volume).toEqual(1.09);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,21 +1,54 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order isEditable()', () => {
it('should return false when the given order is not editable', async() => {
let isEditable = await app.models.Order.isEditable(2);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const isEditable = await models.Order.isEditable(2, options);
expect(isEditable).toBeFalsy();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return false when the given order doesnt exists', async() => {
let isEditable = await app.models.Order.isEditable(99999);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const isEditable = await models.Order.isEditable(999, options);
expect(isEditable).toBeFalsy();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return true when the given order is editable', async() => {
let isEditable = await app.models.Order.isEditable(16);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const isEditable = await models.Order.isEditable(16, options);
expect(isEditable).toBeTruthy();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,36 +1,49 @@
const app = require('vn-loopback/server/server');
let UserError = require('vn-loopback/util/user-error');
const models = require('vn-loopback/server/server').models;
const UserError = require('vn-loopback/util/user-error');
describe('order new()', () => {
let orderId;
afterAll(async() => {
await app.models.Order.destroyById(orderId);
});
it('should throw an error if the client isnt active', async() => {
const tx = await models.Order.beginTransaction({});
let error;
let landed = new Date();
let addressFk = 6;
let agencyModeFk = 1;
try {
const options = {transaction: tx};
await app.models.Order.new(landed, addressFk, agencyModeFk)
.catch(e => {
const landed = new Date();
const addressFk = 6;
const agencyModeFk = 1;
await models.Order.new(landed, addressFk, agencyModeFk, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
});
}
expect(error).toEqual(new UserError(`You can't create an order for a inactive client`));
expect(error).toEqual(new UserError(`You can't create an order for an inactive client`));
});
it('should now create a new order when all conditions are met', async() => {
let landed = new Date();
let addressFk = 121;
let agencyModeFk = 1;
const tx = await models.Order.beginTransaction({});
orderId = await app.models.Order.new(landed, addressFk, agencyModeFk);
try {
const options = {transaction: tx};
let highestOrderIdInFixtures = 3;
const landed = new Date();
const addressFk = 121;
const agencyModeFk = 1;
orderId = await models.Order.new(landed, addressFk, agencyModeFk, options);
const highestOrderIdInFixtures = 3;
expect(orderId).toBeGreaterThan(highestOrderIdInFixtures);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -0,0 +1,24 @@
const models = require('vn-loopback/server/server').models;
describe('order newFromTicket()', () => {
it('should create a new order from an existing ticket', async() => {
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const ticketId = 11;
const orderId = await models.Order.newFromTicket(ticketId, options);
const highestOrderIdInFixtures = 3;
expect(orderId).toBeGreaterThan(highestOrderIdInFixtures);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,36 +1,91 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('order summary()', () => {
it('should return a summary object containing data from 1 order', async() => {
let result = await app.models.Order.summary(1);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.summary(1, options);
expect(result.id).toEqual(1);
expect(result.clientFk).toEqual(1101);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return a summary object containing sales from 1 order', async() => {
let result = await app.models.Order.summary(1);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.summary(1, options);
expect(result.rows.length).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return a summary object containing subTotal for 1 order', async() => {
let result = await app.models.Order.summary(1);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.summary(1, options);
expect(Math.round(result.subTotal * 100) / 100).toEqual(135.60);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return a summary object containing VAT for 1 order', async() => {
let result = await app.models.Order.summary(1);
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.summary(1, options);
expect(Math.round(result.VAT * 100) / 100).toEqual(20.29);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return a summary object containing total for 1 order', async() => {
let result = await app.models.Order.summary(1);
let total = result.subTotal + result.VAT;
let expectedTotal = Math.round(total * 100) / 100;
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
const result = await models.Order.summary(1, options);
const total = result.subTotal + result.VAT;
const expectedTotal = Math.round(total * 100) / 100;
expect(result.total).toEqual(expectedTotal);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,61 +1,93 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
const UserError = require('vn-loopback/util/user-error');
describe('Order updateBasicData', () => {
const orderId = 21;
afterAll(async() => {
let validparams = {note: null};
await app.models.Order.updateBasicData(orderId, validparams);
});
it('should return an error if the order is confirmed', async() => {
const tx = await models.Order.beginTransaction({});
let error;
try {
const options = {transaction: tx};
const params = [];
const orderConfirmed = 1;
let params = [];
let orderConfirmed = 1;
await models.Order.updateBasicData(orderConfirmed, params, options);
await app.models.Order.updateBasicData(orderConfirmed, params)
.catch(e => {
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
});
}
const expectedError = `You can't make changes on the basic data of an confirmed order or with rows`;
expect(error.toString()).toContain(`You can't make changes on the basic data of an confirmed order or with rows`);
expect(error).toEqual(new UserError(expectedError));
});
it('should return an error if the order has rows', async() => {
const tx = await models.Order.beginTransaction({});
let error;
try {
const options = {transaction: tx};
let params = [];
let orderWithRows = 16;
const params = [];
const orderWithRows = 16;
await app.models.Order.updateBasicData(orderWithRows, params)
.catch(e => {
await models.Order.updateBasicData(orderWithRows, params, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
});
}
expect(error.toString()).toContain(`You can't make changes on the basic data of an confirmed order or with rows`);
const expectedError = `You can't make changes on the basic data of an confirmed order or with rows`;
expect(error).toEqual(new UserError(expectedError));
});
it('should skip invalid params', async() => {
const tx = await models.Order.beginTransaction({});
try {
const options = {transaction: tx};
let success;
let invalidparams = {invalid: 'param for update'};
const invalidparams = {invalid: 'param for update'};
await app.models.Order.updateBasicData(orderId, invalidparams)
await models.Order.updateBasicData(orderId, invalidparams, options)
.then(() => success = true);
expect(success).toBeTruthy();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should update the client fiscal data and return the count if changes made', async() => {
let validparams = {note: 'test note'};
const tx = await models.Order.beginTransaction({});
let order = await app.models.Order.findById(orderId);
try {
const options = {transaction: tx};
const validparams = {note: 'test note'};
const order = await models.Order.findById(orderId, null, options);
expect(order.note).toEqual(null);
let result = await app.models.Order.updateBasicData(orderId, validparams);
const result = await models.Order.updateBasicData(orderId, validparams, options);
expect(result.note).toEqual('test note');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -19,17 +19,22 @@ module.exports = Self => {
}
});
Self.summary = async orderId => {
let models = Self.app.models;
let summary = await getOrderData(Self, orderId);
Self.summary = async(orderId, options) => {
const models = Self.app.models;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const summary = await getOrderData(Self, orderId, myOptions);
summary.subTotal = getSubTotal(summary.rows);
summary.VAT = await models.Order.getVAT(orderId);
summary.total = await models.Order.getTotal(orderId);
summary.VAT = await models.Order.getVAT(orderId, myOptions);
summary.total = await models.Order.getTotal(orderId, myOptions);
return summary;
};
async function getOrderData(Self, orderId) {
let filter = {
async function getOrderData(Self, orderId, options) {
const filter = {
include: [
{
relation: 'agencyMode', scope: {fields: ['name']}},
@ -69,7 +74,7 @@ module.exports = Self => {
where: {id: orderId}
};
return await Self.findOne(filter);
return Self.findOne(filter, options);
}
function getSubTotal(rows) {

View File

@ -31,16 +31,27 @@ module.exports = Self => {
}
});
Self.updateBasicData = async(id, params) => {
let models = Self.app.models;
Self.updateBasicData = async(id, params, options) => {
const models = Self.app.models;
const myOptions = {};
let tx;
let order = await models.Order.findById(id);
let orderRows = await models.OrderRow.find({where: {orderFk: id}});
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const order = await models.Order.findById(id, null, myOptions);
const orderRows = await models.OrderRow.find({where: {orderFk: id}}, myOptions);
if (order.isConfirmed || orderRows.length != 0)
throw new UserError(`You can't make changes on the basic data of an confirmed order or with rows`);
let updateParams = pick(params, [
const updateParams = pick(params, [
'clientFk',
'addressFk',
'landed',
@ -48,8 +59,14 @@ module.exports = Self => {
'note',
]);
if (Object.keys(updateParams).length)
await order.updateAttributes(updateParams);
await order.updateAttributes(updateParams, myOptions);
return await order;
if (tx) await tx.commit();
return order;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -1,5 +1,5 @@
You can't create an order for a frozen client: No puedes crear una orden a un cliente congelado
You can't create an order for a inactive client: No puedes crear una orden a un cliente inactivo
You can't create an order for an inactive client: No puedes crear una orden a un cliente inactivo
You can't create an order for a client that doesn't has tax data verified:
No puedes crear una orden a un cliente cuyos datos fiscales no han sido verificados
You can't create an order for a client that has a debt: No puedes crear una orden a un cliente que tiene deuda

View File

@ -29,9 +29,9 @@ describe('route getSuggestedTickets()', () => {
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
expect(result.length).toEqual(1);
expect(result.length).toEqual(4);
expect(anyResult.zoneFk).toEqual(1);
expect(anyResult.agencyModeFk).toEqual(1);
expect(anyResult.agencyModeFk).toEqual(8);
await tx.rollback();
} catch (e) {

View File

@ -11,7 +11,7 @@ describe('ticket filter()', () => {
const filter = {order: 'id DESC'};
const result = await models.Ticket.filter(ctx, filter, options);
expect(result.length).toEqual(24);
expect(result.length).toEqual(27);
await tx.rollback();
} catch (e) {
@ -87,7 +87,7 @@ describe('ticket filter()', () => {
const filter = {};
const result = await models.Ticket.filter(ctx, filter, options);
expect(result.length).toEqual(24);
expect(result.length).toEqual(27);
await tx.rollback();
} catch (e) {
@ -130,7 +130,7 @@ describe('ticket filter()', () => {
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
expect(length).toEqual(7);
expect(length).toEqual(10);
expect(anyResult.state).toMatch(/(Libre|Arreglar)/);
await tx.rollback();
@ -175,7 +175,7 @@ describe('ticket filter()', () => {
const filter = {};
const result = await models.Ticket.filter(ctx, filter, options);
expect(result.length).toEqual(20);
expect(result.length).toEqual(23);
await tx.rollback();
} catch (e) {

View File

@ -10,6 +10,10 @@
</slot-dot-menu>
<slot-body>
<div class="attributes">
<vn-label-value
label="Client"
value="{{$ctrl.ticket.client.id}}">
</vn-label-value>
<vn-label-value
label="State"
value="{{$ctrl.ticket.ticketState.state.name}}">

View File

@ -0,0 +1,8 @@
const Stylesheet = require(`${appPath}/core/stylesheet`);
module.exports = new Stylesheet([
`${appPath}/common/css/layout.css`,
`${appPath}/common/css/report.css`,
`${appPath}/common/css/misc.css`,
`${__dirname}/style.css`])
.mergeStyles();

View File

@ -0,0 +1,31 @@
.grid-block {
font-size: 1.2em
}
.signature .dummy-signature {
width: 400px;
height: 190px;
display: block;
content: '';
overflow: hidden;
clear:both
}
.signature img {
width: 400px
}
.signature table {
width: 100%;
font-size: inherit;
border-collapse: separate;
border-spacing: 0 10px;
}
.signature table tr > td:first-child {
width: 50%
}
.signature table tr > td:last-child {
border-bottom: 1px dashed #CCC
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View File

@ -0,0 +1,99 @@
<!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">
<div class="grid-block">
<p v-html="$t('description', {
socialName: client.socialName,
name: client.name,
address: client.street,
country: client.country,
fiscalID: client.fi
})"></p>
<p v-html="$t('declaration', {
socialName: client.socialName
})"></p>
<p
v-for="(declaration, $index) in $t('declarations')"
v-html="$t('declarations[' + $index + ']', {
socialName: client.socialName,
destinationCountry: ticket.country,
destinationWarehouse: ticket.warehouse
})">
</p>
<div class="columns">
<div class="size50 signature">
<p class="centered">{{client.name}}</p>
<div class="dummy-signature centered"></div>
<p>
<table>
<tbody>
<tr>
<td>{{$t('signer.representative')}}:</td>
<td></td>
</tr>
<tr>
<td>{{$t('signer.representativeRole')}}:</td>
<td></td>
</tr>
<tr>
<td>{{$t('signer.signed')}}:</td>
<td></td>
</tr>
</tbody>
</table>
</p>
</div>
<div class="size50 signature centered">
<p>{{$t('signature')}}</p>
<img v-bind:src="getReportSrc('signature.png')">
<p>
<div>Juan Vicente Ferrer Roig</div>
<div>Director</div>
<p>{{$t('issued', [
'Algemesí',
issued.getDate(),
$t('months')[issued.getMonth()],
issued.getFullYear()])
}}
</p>
</p>
</div>
</div>
<!-- <div class="signature">
<p>{{$t('issued', [
'Algemesí',
invoice.issued.getDate(),
$t('months')[invoice.issued.getMonth()],
invoice.issued.getFullYear()])
}}
</p>
<p><em>({{$t('signature')}})</em></p>
<img v-bind:src="getReportSrc('signature.png')">
<p>
<div>{{$t('signer.name')}}: JUAN VICENTE FERRER ROIG</div>
<div>{{$t('signer.ID')}}: 73943586N</div>
<div>{{$t('signer.position')}}: ADMINISTRADOR</div>
</p>
</div> -->
</div>
</div>
<!-- Footer block -->
<report-footer id="pageFooter"
v-bind:left-text="$t('client', [client.id])"
v-bind="$props">
</report-footer>
</td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -0,0 +1,29 @@
const Component = require(`${appPath}/core/component`);
const reportHeader = new Component('report-header');
const reportFooter = new Component('report-footer');
module.exports = {
name: 'cmr-authorization',
async serverPrefetch() {
this.ticket = await this.findOneFromDef('ticket', [this.ticketId]);
if (!this.ticket)
throw new Error('Something went wrong');
this.client = await this.findOneFromDef('client', [this.ticket.clientFk]);
},
computed: {
issued: function() {
return new Date();
}
},
components: {
'report-header': reportHeader.build(),
'report-footer': reportFooter.build()
},
props: {
ticketId: {
required: true
}
}
};

View File

@ -0,0 +1,41 @@
description: '<em>{socialName}</em> una sociedad debidamente constituida con responsabilidad <em>limitada</em>
y registrada conforme al derecho de sociedades de {country} y aquí representada por
<span>___________________</span>. {socialName}, con domicilio en {address},
CIF <em>{fiscalID}</em>. En adelante denominada {name}.'
issued: 'En {0}, a {1} de {2} de {3}'
client: 'Client {0}'
declaration: '<em>{socialName}</em> declara por la presente que:'
declarations:
- 'Todas las compras realizadas por {socialName} con Verdnatura Levante, S.L. se
entregan, Ex Works (Incoterms), en el almacén de Verdnatura Levante, S.L. situado en
{destinationWarehouse}.'
- '{socialName} reconoce que es importante para Verdnatura Levante, S.L. tener
comprobante de la entrega intracomunitaria de la mercancía a {destinationCountry} para
poder facturar con 0% de IVA.'
- 'Por tanto, al firmar este acuerdo, {socialName} declara que todos los bienes que
se compren a Verdnatura Levante, S.L. serán entregados a {destinationCountry}.'
- 'Además, {socialName} deberá, a primera solicitud de Verdnatura Levante, S.L.,
proporcionar una prueba de que todos los productos comprados a Verdnatura Levante, S.L. han
sido entregados en {destinationCountry}.'
- 'Además de lo anterior, Verdnatura Levante, S.L. proporcionará a {socialName}
un resumen mensual en el que se incluyen todas las facturas (y las entregas correspondientes).
{socialName} firmará y devolverá el resumen mensual a Verdnatura Levante,
S.L. dentro de los 5 días posteriores a la recepción del resumen.'
signature: Verdnatura Levante, S.L.
signer:
representative: Representante
representativeRole: Cargo del representante
signed: Fecha de firma
months:
- 'Enero'
- 'Febrero'
- 'Marzo'
- 'Abril'
- 'Mayo'
- 'Junio'
- 'Julio'
- 'Agosto'
- 'Septiembre'
- 'Octubre'
- 'Noviembre'
- 'Diciembre'

View File

@ -0,0 +1,10 @@
SELECT
c.id,
c.socialName,
c.name,
c.fi,
c.street,
cty.country
FROM client c
JOIN country cty ON cty.id = c.countryFk
WHERE c.id = ?

View File

@ -0,0 +1,12 @@
SELECT
t.id,
t.clientFk,
cty.country,
w.name AS warehouse
FROM ticket t
JOIN warehouse w ON w.id = t.warehouseFk
JOIN address a ON a.id = t.addressFk
JOIN province p ON p.id = a.provinceFk
JOIN autonomy au ON au.id = p.autonomyFk
JOIN country cty ON cty.id = au.countryFk
WHERE t.id = ?