diff --git a/services/db/tests/vn/buyUltimate.spec.js b/services/db/tests/vn/buyUltimate.spec.js index 63539602e..7e0785baa 100644 --- a/services/db/tests/vn/buyUltimate.spec.js +++ b/services/db/tests/vn/buyUltimate.spec.js @@ -1,25 +1,34 @@ const app = require(`../../../ticket/server/server`); +const server = require(`../../../loopback/server/server`); +const ParameterizedSQL = server.loopbackConnector.ParameterizedSQL; describe('buyUltimate()', () => { const today = new Date(); it(`should create buyUltimate temporal table and update it's values`, async() => { + let stmts = []; + let stmt; + + stmts.push('START TRANSACTION'); + let params = { warehouseFk: 1, date: today }; - let query = ` - START TRANSACTION; - CALL vn.buyUltimate(?, ?); - SELECT * FROM tmp.buyUltimate ORDER BY 'id' DESC; - ROLLBACK;`; - - let result = await app.models.Ticket.rawSql(query, [ + stmt = new ParameterizedSQL('CALL vn.buyUltimate(?, ?)', [ params.warehouseFk, params.date ]); + stmts.push(stmt); - let buyUltimateTable = result[2]; + let buyUltimateTableIndex = stmts.push(`SELECT * FROM tmp.buyUltimate ORDER BY itemFk ASC`) - 1; + + stmts.push('ROLLBACK'); + + let sql = ParameterizedSQL.join(stmts, ';'); + let result = await app.models.Ticket.rawStmt(sql); + + let buyUltimateTable = result[buyUltimateTableIndex]; expect(buyUltimateTable.length).toEqual(4); diff --git a/services/db/tests/vn/buyUltimateFromInterval.spec.js b/services/db/tests/vn/buyUltimateFromInterval.spec.js index 02402eb87..d558c3cf6 100644 --- a/services/db/tests/vn/buyUltimateFromInterval.spec.js +++ b/services/db/tests/vn/buyUltimateFromInterval.spec.js @@ -1,4 +1,6 @@ const app = require(`../../../ticket/server/server`); +const server = require(`../../../loopback/server/server`); +const ParameterizedSQL = server.loopbackConnector.ParameterizedSQL; describe('buyUltimateFromInterval()', () => { let today; @@ -19,25 +21,32 @@ describe('buyUltimateFromInterval()', () => { }); it(`should create a temporal table with it's data`, async() => { + let stmts = []; + let stmt; + + stmts.push('START TRANSACTION'); + let params = { warehouseFk: 1, started: today, ended: today }; - let query = ` - START TRANSACTION; - CALL vn.buyUltimateFromInterval(?, ?, ?); - SELECT * FROM tmp.buyUltimateFromInterval; - ROLLBACK;`; - - let result = await app.models.Ticket.rawSql(query, [ + stmt = new ParameterizedSQL('CALL vn.buyUltimateFromInterval(?, ?, ?)', [ params.warehouseFk, params.started, params.ended ]); + stmts.push(stmt); - let buyUltimateFromIntervalTable = result[2]; + let buyUltimateFromIntervalTableIndex = stmts.push(`SELECT * FROM tmp.buyUltimateFromInterval`) - 1; + + stmts.push('ROLLBACK'); + + let sql = ParameterizedSQL.join(stmts, ';'); + let result = await app.models.Ticket.rawStmt(sql); + + let buyUltimateFromIntervalTable = result[buyUltimateFromIntervalTableIndex]; expect(buyUltimateFromIntervalTable.length).toEqual(2); diff --git a/services/db/tests/vn/logAddWithUser.spec.js b/services/db/tests/vn/logAddWithUser.spec.js index da85168e2..73b05964c 100644 --- a/services/db/tests/vn/logAddWithUser.spec.js +++ b/services/db/tests/vn/logAddWithUser.spec.js @@ -1,7 +1,14 @@ const app = require(`../../../ticket/server/server`); +const server = require(`../../../loopback/server/server`); +const ParameterizedSQL = server.loopbackConnector.ParameterizedSQL; describe('logAddWithUser()', () => { it('should log any action taken by the user in a table ending in Log', async() => { + let stmts = []; + let stmt; + + stmts.push('START TRANSACTION'); + let params = { ticketFk: 1, userId: 9, @@ -10,21 +17,26 @@ describe('logAddWithUser()', () => { description: 'we are testing stuff' }; - let query = ` - START TRANSACTION; - CALL vn.logAddWithUser(?, ?, ?, ?, ?); - SELECT * FROM vn.ticketLog WHERE description = ?; - ROLLBACK;`; - let result = await app.models.Ticket.rawSql(query, [ + stmt = new ParameterizedSQL('CALL vn.logAddWithUser(?, ?, ?, ?, ?)', [ params.ticketFk, params.userId, params.actionCode, params.targetEntity, - params.description, params.description ]); + stmts.push(stmt); - savedDescription = result[2][0].description; + stmt = new ParameterizedSQL('SELECT * FROM vn.ticketLog WHERE description = ?', [ + params.description + ]); + let ticketLogIndex = stmts.push(stmt) - 1; + + stmts.push('ROLLBACK'); + + let sql = ParameterizedSQL.join(stmts, ';'); + let result = await app.models.Ticket.rawStmt(sql); + + savedDescription = result[ticketLogIndex][0].description; expect(savedDescription).toEqual(params.description); }); diff --git a/services/db/tests/vn/ticketCalculateClon.spec.js b/services/db/tests/vn/ticketCalculateClon.spec.js index 3e1118b37..c2e9e2b59 100644 --- a/services/db/tests/vn/ticketCalculateClon.spec.js +++ b/services/db/tests/vn/ticketCalculateClon.spec.js @@ -1,8 +1,15 @@ const app = require(`../../../ticket/server/server`); +const server = require(`../../../loopback/server/server`); +const ParameterizedSQL = server.loopbackConnector.ParameterizedSQL; describe('ticket ticketCalculateClon()', () => { const today = new Date(); it('should add the ticket to the order containing the original ticket', async() => { + let stmts = []; + let stmt; + + stmts.push('START TRANSACTION'); + let params = { clientFk: 101, shipped: today, @@ -16,14 +23,7 @@ describe('ticket ticketCalculateClon()', () => { originalTicketId: 11 }; - let query = ` - START TRANSACTION; - CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @result); - CALL vn.ticketCalculateClon(@result, ?); - SELECT * FROM vn.orderTicket WHERE ticketFk = @result; - SELECT * FROM tmp.agencyHourGetShipped; - ROLLBACK;`; - let result = await app.models.Ticket.rawSql(query, [ + stmt = new ParameterizedSQL('CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @result)', [ params.clientFk, params.shipped, params.warehouseFk, @@ -32,21 +32,37 @@ describe('ticket ticketCalculateClon()', () => { params.agencyType, params.routeFk, params.landed, - params.userId, - params.originalTicketId + params.userId ]); + stmts.push(stmt); + + stmt = new ParameterizedSQL('CALL vn.ticketCalculateClon(@result, ?)', [params.originalTicketId]); + stmts.push(stmt); + + let orderIndex = stmts.push(`SELECT * FROM vn.orderTicket WHERE ticketFk = @result`) - 1; + let angencyHourIndex = stmts.push(`SELECT * FROM tmp.agencyHourGetShipped`) - 1; + + stmts.push('ROLLBACK'); + + let sql = ParameterizedSQL.join(stmts, ';'); + let result = await app.models.Ticket.rawStmt(sql); let expectedOrder = 11; let newestTicketIdInFixtures = 21; - expect(result[3][0].orderFk).toEqual(expectedOrder); - expect(result[3][0].ticketFk).toBeGreaterThan(newestTicketIdInFixtures); - expect(result[4][0].warehouseFk).toEqual(1); - expect(result[4][0].shipped).toBeDefined(); - expect(result[4][0].landed).toBeDefined(); + expect(result[orderIndex][0].orderFk).toEqual(expectedOrder); + expect(result[orderIndex][0].ticketFk).toBeGreaterThan(newestTicketIdInFixtures); + expect(result[angencyHourIndex][0].warehouseFk).toEqual(1); + expect(result[angencyHourIndex][0].shipped).toBeDefined(); + expect(result[angencyHourIndex][0].landed).toBeDefined(); }); it('should add the ticket to the order containing the original ticket and generate landed value if it was null', async() => { + let stmts = []; + let stmt; + + stmts.push('START TRANSACTION'); + let params = { clientFk: 101, shipped: today, @@ -60,14 +76,7 @@ describe('ticket ticketCalculateClon()', () => { originalTicketId: 11 }; - let query = ` - START TRANSACTION; - CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @result); - CALL vn.ticketCalculateClon(@result, ?); - SELECT * FROM vn.orderTicket WHERE ticketFk = @result; - SELECT * FROM tmp.agencyHourGetShipped; - ROLLBACK;`; - let result = await app.models.Ticket.rawSql(query, [ + stmt = new ParameterizedSQL('CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @result)', [ params.clientFk, params.shipped, params.warehouseFk, @@ -76,17 +85,28 @@ describe('ticket ticketCalculateClon()', () => { params.agencyType, params.routeFk, params.landed, - params.userId, - params.originalTicketId + params.userId ]); + stmts.push(stmt); + + stmt = new ParameterizedSQL('CALL vn.ticketCalculateClon(@result, ?)', [params.originalTicketId]); + stmts.push(stmt); + + let orderIndex = stmts.push(`SELECT * FROM vn.orderTicket WHERE ticketFk = @result`) - 1; + let angencyHourIndex = stmts.push(`SELECT * FROM tmp.agencyHourGetShipped`) - 1; + + stmts.push('ROLLBACK'); + + let sql = ParameterizedSQL.join(stmts, ';'); + let result = await app.models.Ticket.rawStmt(sql); let expectedOrder = 11; let newestTicketIdInFixtures = 21; - expect(result[3][0].orderFk).toEqual(expectedOrder); - expect(result[3][0].ticketFk).toBeGreaterThan(newestTicketIdInFixtures); - expect(result[4][0].warehouseFk).toEqual(1); - expect(result[4][0].shipped).toBeDefined(); - expect(result[4][0].landed).toBeDefined(); + expect(result[orderIndex][0].orderFk).toEqual(expectedOrder); + expect(result[orderIndex][0].ticketFk).toBeGreaterThan(newestTicketIdInFixtures); + expect(result[angencyHourIndex][0].warehouseFk).toEqual(1); + expect(result[angencyHourIndex][0].shipped).toBeDefined(); + expect(result[angencyHourIndex][0].landed).toBeDefined(); }); }); diff --git a/services/db/tests/vn/ticketComponentUpdateSale.spec.js b/services/db/tests/vn/ticketComponentUpdateSale.spec.js new file mode 100644 index 000000000..a0f63ee8b --- /dev/null +++ b/services/db/tests/vn/ticketComponentUpdateSale.spec.js @@ -0,0 +1,289 @@ +const app = require(`../../../ticket/server/server`); +const server = require(`../../../loopback/server/server`); +const ParameterizedSQL = server.loopbackConnector.ParameterizedSQL; + +describe('ticketComponentUpdateSale()', () => { + it(`should update the sale price when option ONE using the base components and reclaculate only the ones with isRenewable TRUE`, async() => { + let stmts = []; + let stmt; + + let params = { + warehouseFk: 1, + ticketFk: 1 + }; + + stmts.push('START TRANSACTION'); + + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale'); + + // createSaleTempTable code comes from vn.ticketComponentUpdate procedure + let createSaleTempTable = ` + CREATE TEMPORARY TABLE tmp.sale + (PRIMARY KEY (saleFk)) + ENGINE = MEMORY + SELECT id AS saleFk, ? warehouseFk + FROM sale s WHERE s.ticketFk = ? + `; + + stmt = new ParameterizedSQL(createSaleTempTable, [ + params.warehouseFk, + params.ticketFk + ]); + stmts.push(stmt); + + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponent'); + + // createTicketComponentTable code comes partially from vn.ticketComponenetCalculate procedure + let createTicketComponentTable = ` + CREATE TEMPORARY TABLE tmp.ticketComponent ( + warehouseFk INT UNSIGNED NOT NULL, + itemFk INT NOT NULL, + componentFk INT UNSIGNED NOT NULL, + cost DECIMAL(10,4) NOT NULL, + INDEX itemWarehouse USING BTREE (itemFk ASC, warehouseFk ASC), + UNIQUE INDEX itemWarehouseComponent (itemFk ASC, warehouseFk ASC, componentFk ASC)) + `; + + stmts.push(createTicketComponentTable); + + let insertTicketComponentTable = ` + INSERT INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost) + VALUES + (1 , 2 , 23 , 999.00), + (1 , 2 , 28 , 2.00), + (1 , 4 , 23 , 999.00), + (1 , 4 , 28 , 1.00) + `; + + stmts.push(insertTicketComponentTable); + + let updateComponentTwentyThree = ` + UPDATE vn.saleComponent + SET value = '5' + WHERE saleFk = 1 AND componentFk = 23 + `; + + stmts.push(updateComponentTwentyThree); + + let updateComponentTwentyEight = ` + UPDATE vn.saleComponent + SET value = '5' + WHERE saleFk = 1 AND componentFk = 28 + `; + + stmts.push(updateComponentTwentyEight); + + let priceFixtedToZero = ` + UPDATE vn.sale + SET priceFixed = 0 + WHERE id = 1 + `; + + stmts.push(priceFixtedToZero); + + let firstSalePriceIndexBefore = stmts.push('SELECT price FROM vn.sale WHERE id = 1') - 1; + + stmts.push('CALL vn.ticketComponentUpdateSale(1)'); + + let firstSalePriceIndexAfter = stmts.push('SELECT price FROM vn.sale WHERE id = 1') - 1; + + stmts.push('ROLLBACK'); + + let sql = ParameterizedSQL.join(stmts, ';'); + let result = await app.models.Ticket.rawStmt(sql); + + expect(result[firstSalePriceIndexBefore][0].price).toEqual(9.1); + expect(result[firstSalePriceIndexAfter][0].price).toEqual(5); + }); + + it(`should keep the sale price when option TWO using the base components and save the difference in a new component`, async() => { + let stmts = []; + let stmt; + + let params = { + warehouseFk: 1, + ticketFk: 1 + }; + + stmts.push('START TRANSACTION'); + + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale'); + + // createSaleTempTable code comes from vn.ticketComponentUpdate procedure + let createSaleTempTable = ` + CREATE TEMPORARY TABLE tmp.sale + (PRIMARY KEY (saleFk)) + ENGINE = MEMORY + SELECT id AS saleFk, ? warehouseFk + FROM sale s WHERE s.ticketFk = ? + `; + + stmt = new ParameterizedSQL(createSaleTempTable, [ + params.warehouseFk, + params.ticketFk + ]); + stmts.push(stmt); + + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponent'); + + // createTicketComponentTable code comes partially from vn.ticketComponenetCalculate procedure + let createTicketComponentTable = ` + CREATE TEMPORARY TABLE tmp.ticketComponent ( + warehouseFk INT UNSIGNED NOT NULL, + itemFk INT NOT NULL, + componentFk INT UNSIGNED NOT NULL, + cost DECIMAL(10,4) NOT NULL, + INDEX itemWarehouse USING BTREE (itemFk ASC, warehouseFk ASC), + UNIQUE INDEX itemWarehouseComponent (itemFk ASC, warehouseFk ASC, componentFk ASC)) + `; + + stmts.push(createTicketComponentTable); + + let insertTicketComponentTable = ` + INSERT INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost) + VALUES + (1 , 2 , 23 , 999.00), + (1 , 2 , 28 , 2.00), + (1 , 4 , 23 , 999.00), + (1 , 4 , 28 , 1.00) + `; + + stmts.push(insertTicketComponentTable); + + let updateComponentTwentyThree = ` + UPDATE vn.saleComponent + SET value = '5' + WHERE saleFk = 1 AND componentFk = 23 + `; + + stmts.push(updateComponentTwentyThree); + + let updateComponentTwentyEight = ` + UPDATE vn.saleComponent + SET value = '5' + WHERE saleFk = 1 AND componentFk = 28 + `; + + stmts.push(updateComponentTwentyEight); + + let priceFixtedToZero = ` + UPDATE vn.sale + SET priceFixed = 0 + WHERE id = 1 + `; + + stmts.push(priceFixtedToZero); + + let firstSalePriceIndexBefore = stmts.push('SELECT price FROM vn.sale WHERE id = 1') - 1; + + stmts.push('CALL vn.ticketComponentUpdateSale(2)'); + + let addedComponentIndex = stmts.push('SELECT * FROM vn.saleComponent WHERE saleFk = 1 AND componentFk = 17') - 1; + let firstSalePriceIndexAfter = stmts.push('SELECT price FROM vn.sale WHERE id = 1') - 1; + + stmts.push('ROLLBACK'); + + let sql = ParameterizedSQL.join(stmts, ';'); + let result = await app.models.Ticket.rawStmt(sql); + + expect(result[addedComponentIndex][0].value).toEqual(4.1); + expect(result[firstSalePriceIndexBefore][0].price).toEqual(result[firstSalePriceIndexAfter][0].price); + }); + + it(`should not change the sale price when option SEVEN, instead it stores 80% and 20% of the price in two components and any price difference in a third one`, async() => { + let stmts = []; + let stmt; + + let params = { + warehouseFk: 1, + ticketFk: 1 + }; + + stmts.push('START TRANSACTION'); + + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale'); + + // createSaleTempTable code comes from vn.ticketComponentUpdate procedure + let createSaleTempTable = ` + CREATE TEMPORARY TABLE tmp.sale + (PRIMARY KEY (saleFk)) + ENGINE = MEMORY + SELECT id AS saleFk, ? warehouseFk + FROM sale s WHERE s.ticketFk = ? + `; + + stmt = new ParameterizedSQL(createSaleTempTable, [ + params.warehouseFk, + params.ticketFk + ]); + stmts.push(stmt); + + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponent'); + + // createTicketComponentTable code comes partially from vn.ticketComponenetCalculate procedure + let createTicketComponentTable = ` + CREATE TEMPORARY TABLE tmp.ticketComponent ( + warehouseFk INT UNSIGNED NOT NULL, + itemFk INT NOT NULL, + componentFk INT UNSIGNED NOT NULL, + cost DECIMAL(10,4) NOT NULL, + INDEX itemWarehouse USING BTREE (itemFk ASC, warehouseFk ASC), + UNIQUE INDEX itemWarehouseComponent (itemFk ASC, warehouseFk ASC, componentFk ASC)) + `; + + stmts.push(createTicketComponentTable); + + let insertTicketComponentTable = ` + INSERT INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost) + VALUES + (1 , 2 , 29 , 999.00), + (1 , 2 , 28 , 2.00), + (1 , 4 , 29 , 999.00), + (1 , 4 , 28 , 1.00) + `; + + stmts.push(insertTicketComponentTable); + + let updateComponentTwentyEight = ` + UPDATE vn.saleComponent + SET value = '5' + WHERE saleFk = 1 AND componentFk = 28 + `; + + stmts.push(updateComponentTwentyEight); + + let updateComponentTwentyNine = ` + UPDATE vn.saleComponent + SET value = '5' + WHERE saleFk = 1 AND componentFk = 29 + `; + + stmts.push(updateComponentTwentyNine); + + let priceFixtedToZero = ` + UPDATE vn.sale + SET priceFixed = 0 + WHERE id = 1 + `; + + stmts.push(priceFixtedToZero); + + let firstSalePriceIndexBefore = stmts.push('SELECT price FROM vn.sale WHERE id = 1') - 1; + + stmts.push('CALL vn.ticketComponentUpdateSale(7)'); + + let componentTwentyEightIndex = stmts.push('SELECT * FROM vn.saleComponent WHERE saleFk = 1 AND componentFk = 28') - 1; + let componentTwentyNineIndex = stmts.push('SELECT * FROM vn.saleComponent WHERE saleFk = 1 AND componentFk = 29') - 1; + let firstSalePriceIndexAfter = stmts.push('SELECT price FROM vn.sale WHERE id = 1') - 1; + + stmts.push('ROLLBACK'); + + let sql = ParameterizedSQL.join(stmts, ';'); + let result = await app.models.Ticket.rawStmt(sql); + + expect(result[componentTwentyEightIndex][0].value).toEqual(1.6); + expect(result[componentTwentyNineIndex][0].value).toEqual(0.4); + expect(result[firstSalePriceIndexBefore][0].price).toEqual(result[firstSalePriceIndexAfter][0].price); + }); +}); + diff --git a/services/loopback/common/models/vn-model.js b/services/loopback/common/models/vn-model.js index bccb23a34..ba27f8e6f 100644 --- a/services/loopback/common/models/vn-model.js +++ b/services/loopback/common/models/vn-model.js @@ -256,6 +256,8 @@ module.exports = function(Self) { ]); }; + Self.ParameterizedSQL = ParameterizedSQL; + require('../methods/vn-model/installMethod')(Self); require('../methods/vn-model/validateBinded')(Self); require('../methods/vn-model/rewriteDbError')(Self); diff --git a/services/loopback/server/server.js b/services/loopback/server/server.js index b1ccdb6aa..0fcdfae79 100644 --- a/services/loopback/server/server.js +++ b/services/loopback/server/server.js @@ -4,6 +4,7 @@ let DataSource = require('loopback-datasource-juggler').DataSource; let fs = require('fs-extra'); let i18n = require('i18n'); let path = require('path'); +const loopbackConnector = require('loopback-connector'); let _resolveConnector = DataSource._resolveConnector; @@ -21,6 +22,7 @@ DataSource._resolveConnector = function(name) { module.exports = { loopback: loopback, + loopbackConnector: loopbackConnector, boot: vnBoot };