diff --git a/CHANGELOG.md b/CHANGELOG.md index dde790aaa..0d476fb46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2312.01] - 2023-04-06 ### Added -- +- (Monitor tickets) Muestra un icono al lado de la zona, si el ticket es frágil y se envía por agencia ### Changed -- +- (Envíos -> Extra comunitarios) Se agrupan las entradas del mismo travel. Añadidos campos Referencia y Importe. ### Fixed - diff --git a/back/methods/chat/send.js b/back/methods/chat/send.js index 915120d49..79b20e307 100644 --- a/back/methods/chat/send.js +++ b/back/methods/chat/send.js @@ -30,16 +30,23 @@ module.exports = Self => { const recipient = to.replace('@', ''); if (sender.name != recipient) { - await models.Chat.create({ + const chat = await models.Chat.create({ senderFk: sender.id, recipient: to, dated: Date.vnNew(), checkUserStatus: 0, message: message, - status: 0, + status: 'sending', attempts: 0 }); + try { + await Self.sendMessage(chat.senderFk, chat.recipient, chat.message); + await Self.updateChat(chat, 'sent'); + } catch (error) { + await Self.updateChat(chat, 'error', error); + } + return true; } diff --git a/back/methods/chat/sendCheckingPresence.js b/back/methods/chat/sendCheckingPresence.js index 883a1b693..29232490a 100644 --- a/back/methods/chat/sendCheckingPresence.js +++ b/back/methods/chat/sendCheckingPresence.js @@ -24,18 +24,13 @@ module.exports = Self => { } }); - Self.sendCheckingPresence = async(ctx, recipientId, message, options) => { + Self.sendCheckingPresence = async(ctx, recipientId, message) => { if (!recipientId) return false; - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - const models = Self.app.models; const userId = ctx.req.accessToken.userId; - const sender = await models.Account.findById(userId); - const recipient = await models.Account.findById(recipientId, null, myOptions); + const sender = await models.Account.findById(userId, {fields: ['id']}); + const recipient = await models.Account.findById(recipientId, null); // Prevent sending messages to yourself if (recipientId == userId) return false; @@ -46,16 +41,23 @@ module.exports = Self => { if (process.env.NODE_ENV == 'test') message = `[Test:Environment to user ${userId}] ` + message; - await models.Chat.create({ + const chat = await models.Chat.create({ senderFk: sender.id, recipient: `@${recipient.name}`, dated: Date.vnNew(), checkUserStatus: 1, message: message, - status: 0, + status: 'sending', attempts: 0 }); + try { + await Self.sendCheckingUserStatus(chat); + await Self.updateChat(chat, 'sent'); + } catch (error) { + await Self.updateChat(chat, 'error', error); + } + return true; }; }; diff --git a/back/methods/chat/sendQueued.js b/back/methods/chat/sendQueued.js index 66fbfcdc5..ef1a417ab 100644 --- a/back/methods/chat/sendQueued.js +++ b/back/methods/chat/sendQueued.js @@ -3,7 +3,6 @@ module.exports = Self => { Self.remoteMethodCtx('sendQueued', { description: 'Send a RocketChat message', accessType: 'WRITE', - accepts: [], returns: { type: 'object', root: true @@ -16,14 +15,17 @@ module.exports = Self => { Self.sendQueued = async() => { const models = Self.app.models; - const maxAttempts = 3; - const sentStatus = 1; - const errorStatus = 2; const chats = await models.Chat.find({ where: { - status: {neq: sentStatus}, - attempts: {lt: maxAttempts} + status: { + nin: [ + 'sent', + 'sending' + ] + + }, + attempts: {lt: 3} } }); @@ -31,16 +33,16 @@ module.exports = Self => { if (chat.checkUserStatus) { try { await Self.sendCheckingUserStatus(chat); - await updateChat(chat, sentStatus); + await Self.updateChat(chat, 'sent'); } catch (error) { - await updateChat(chat, errorStatus, error); + await Self.updateChat(chat, 'error', error); } } else { try { await Self.sendMessage(chat.senderFk, chat.recipient, chat.message); - await updateChat(chat, sentStatus); + await Self.updateChat(chat, 'sent'); } catch (error) { - await updateChat(chat, errorStatus, error); + await Self.updateChat(chat, 'error', error); } } } @@ -128,15 +130,17 @@ module.exports = Self => { * @param {object} chat - The chat * @param {string} status - The new status * @param {string} error - The error + * @param {object} options - Query options * @return {Promise} - The request promise - */ - async function updateChat(chat, status, error) { + */ + + Self.updateChat = async(chat, status, error) => { return chat.updateAttributes({ status: status, attempts: ++chat.attempts, error: error }); - } + }; /** * Returns the current user status on Rocketchat diff --git a/back/methods/chat/spec/sendQueued.spec.js b/back/methods/chat/spec/sendQueued.spec.js index ed791756b..67cd47f4a 100644 --- a/back/methods/chat/spec/sendQueued.spec.js +++ b/back/methods/chat/spec/sendQueued.spec.js @@ -10,7 +10,7 @@ describe('Chat sendCheckingPresence()', () => { const chat = { checkUserStatus: 1, - status: 0, + status: 'pending', attempts: 0 }; @@ -27,7 +27,7 @@ describe('Chat sendCheckingPresence()', () => { const chat = { checkUserStatus: 0, - status: 0, + status: 'pending', attempts: 0 }; diff --git a/back/methods/collection/spec/setSaleQuantity.spec.js b/back/methods/collection/spec/setSaleQuantity.spec.js index 63dc3bd2d..acdf2ebb5 100644 --- a/back/methods/collection/spec/setSaleQuantity.spec.js +++ b/back/methods/collection/spec/setSaleQuantity.spec.js @@ -1,6 +1,21 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('setSaleQuantity()', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it('should change quantity sale', async() => { const tx = await models.Ticket.beginTransaction({}); diff --git a/db/changes/231201/00-chatRefactor.sql b/db/changes/231201/00-chatRefactor.sql new file mode 100644 index 000000000..66d1bf3bf --- /dev/null +++ b/db/changes/231201/00-chatRefactor.sql @@ -0,0 +1,16 @@ +ALTER TABLE `vn`.`chat` ADD statusNew enum('pending','sent','error','sending') DEFAULT 'pending' NOT NULL; + +UPDATE `vn`.`chat` + SET statusNew = 'pending' +WHERE status = 0; + +UPDATE `vn`.`chat` + SET statusNew = 'sent' +WHERE status = 1; + +UPDATE `vn`.`chat` + SET statusNew = 'error' +WHERE status = 2; + +ALTER TABLE `vn`.`chat` CHANGE status status__ tinyint(1) DEFAULT NULL NULL; +ALTER TABLE `vn`.`chat` CHANGE statusNew status enum('pending','sent','error','sending') CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT 'pending' NOT NULL; diff --git a/db/changes/231201/00-itemType_isFragile.sql b/db/changes/231201/00-itemType_isFragile.sql new file mode 100644 index 000000000..5b25288f3 --- /dev/null +++ b/db/changes/231201/00-itemType_isFragile.sql @@ -0,0 +1,14 @@ +ALTER TABLE `vn`.`itemType` ADD isFragile tinyint(1) NULL; +ALTER TABLE `vn`.`itemType` MODIFY COLUMN isFragile tinyint(1) DEFAULT 0 NOT NULL; + +UPDATE `vn`.`itemType` + SET isFragile = 1 +WHERE code IN ('ZKA', 'ZKE'); + +UPDATE `vn`.`itemType` + SET isFragile = 1 +WHERE id IN (SELECT it.id + FROM itemCategory ic + JOIN itemType it ON it.categoryFk = ic.id + WHERE ic.code = 'plant'); + diff --git a/db/changes/231201/00-ticket_getWarnings.sql b/db/changes/231201/00-ticket_getWarnings.sql new file mode 100644 index 000000000..5253b58ab --- /dev/null +++ b/db/changes/231201/00-ticket_getWarnings.sql @@ -0,0 +1,47 @@ +DROP PROCEDURE IF EXISTS `vn`.`ticket_getWarnings`; + +DELIMITER $$ +$$ +CREATE PROCEDURE `vn`.`ticket_getWarnings`() +BEGIN +/** + * Calcula las adventencias para un conjunto de tickets. + * Agrupados por ticket + * + * @table tmp.sale_getWarnings(ticketFk) Identificadores de los tickets a calcular + * @return tmp.ticket_warnings + */ + DROP TEMPORARY TABLE IF EXISTS tmp.sale_warnings; + CREATE TEMPORARY TABLE tmp.sale_warnings ( + ticketFk INT(11), + saleFk INT(11), + isFragile INTEGER(1) DEFAULT 0, + PRIMARY KEY (ticketFk, saleFk) + ) ENGINE = MEMORY; + + -- Frágil + INSERT INTO tmp.sale_warnings(ticketFk, saleFk, isFragile) + SELECT tt.ticketFk, s.id, TRUE + FROM tmp.sale_getWarnings tt + LEFT JOIN sale s ON s.ticketFk = tt.ticketFk + LEFT JOIN item i ON i.id = s.itemFk + LEFT JOIN itemType it ON it.id = i.typeFk + LEFT JOIN agencyMode am ON am.id = tt.agencyModeFk + LEFT JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk + WHERE dm.code IN ('AGENCY') + AND it.isFragile; + + DROP TEMPORARY TABLE IF EXISTS tmp.ticket_warnings; + CREATE TEMPORARY TABLE tmp.ticket_warnings + (PRIMARY KEY (ticketFk)) + ENGINE = MEMORY + SELECT + sw.ticketFk, + MAX(sw.isFragile) AS isFragile + FROM tmp.sale_warnings sw + GROUP BY sw.ticketFk; + + DROP TEMPORARY TABLE + tmp.sale_warnings; +END$$ +DELIMITER ; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 22c0d5106..1f240b684 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -501,7 +501,8 @@ INSERT INTO `vn`.`observationType`(`id`,`description`, `code`) (3, 'Delivery', 'delivery'), (4, 'SalesPerson', 'salesPerson'), (5, 'Administrative', 'administrative'), - (6, 'Weight', 'weight'); + (6, 'Weight', 'weight'), + (7, 'InvoiceOut', 'invoiceOut'); INSERT INTO `vn`.`addressObservation`(`id`,`addressFk`,`observationTypeFk`,`description`) VALUES @@ -738,7 +739,9 @@ INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `des (9, 23, 5, 'care with the dog'), (10, 23, 4, 'Reclama ticket: 8'), (11, 24, 4, 'Reclama ticket: 7'), - (12, 11, 3, 'Delivery after 10am'); + (12, 11, 3, 'Delivery after 10am'), + (13, 1, 7, 'observation of ticket one'), + (14, 2, 7, 'observation of ticket two'); -- FIX for state hours on local, inter_afterInsert -- UPDATE vncontrol.inter SET odbc_date = DATE_ADD(util.VN_CURDATE(), INTERVAL -10 SECOND); @@ -838,14 +841,14 @@ INSERT INTO `vn`.`temperature`(`code`, `name`, `description`) ('warm', 'Warm', 'Warm'), ('cool', 'Cool', 'Cool'); -INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`, `workerFk`, `isPackaging`, `temperatureFk`) +INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`, `workerFk`, `isPackaging`, `temperatureFk`, `isFragile`) VALUES - (1, 'CRI', 'Crisantemo', 2, 31, 35, 0, 'cool'), - (2, 'ITG', 'Anthurium', 1, 31, 35, 0, 'cool'), - (3, 'WPN', 'Paniculata', 2, 31, 35, 0, 'cool'), - (4, 'PRT', 'Delivery ports', 3, NULL, 35, 1, 'warm'), - (5, 'CON', 'Container', 3, NULL, 35, 1, 'warm'), - (6, 'ALS', 'Alstroemeria', 1, 31, 16, 0, 'warm'); + (1, 'CRI', 'Crisantemo', 2, 31, 35, 0, 'cool', 0), + (2, 'ITG', 'Anthurium', 1, 31, 35, 0, 'cool', 1), + (3, 'WPN', 'Paniculata', 2, 31, 35, 0, 'cool', 0), + (4, 'PRT', 'Delivery ports', 3, NULL, 35, 1, 'warm', 0), + (5, 'CON', 'Container', 3, NULL, 35, 1, 'warm', 0), + (6, 'ALS', 'Alstroemeria', 1, 31, 16, 0, 'warm', 1); INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`) VALUES @@ -2631,8 +2634,8 @@ INSERT INTO `vn`.`supplierAgencyTerm` (`agencyFk`, `supplierFk`, `minimumPackage INSERT INTO `vn`.`chat` (`senderFk`, `recipient`, `dated`, `checkUserStatus`, `message`, `status`, `attempts`) VALUES - (1101, '@PetterParker', util.VN_CURDATE(), 1, 'First test message', 0, 0), - (1101, '@PetterParker', util.VN_CURDATE(), 0, 'Second test message', 0, 0); + (1101, '@PetterParker', util.VN_CURDATE(), 1, 'First test message', 0, 'sent'), + (1101, '@PetterParker', util.VN_CURDATE(), 0, 'Second test message', 0, 'pending'); INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index f20d75310..f4c67f002 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -524,7 +524,6 @@ export default { }, itemLog: { anyLineCreated: 'vn-item-log > vn-log vn-tbody > vn-tr', - fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) table tr:nth-child(4) td.after', }, ticketSummary: { header: 'vn-ticket-summary > vn-card > h5', @@ -1040,7 +1039,6 @@ export default { boss: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bossFk"]', role: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.roleFk"]', iban: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.iban"]', - switft: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bankEntityFk"]', createButton: 'vn-worker-create vn-submit[label="Create"]', }, workerPda: { diff --git a/e2e/paths/03-worker/04_time_control.spec.js b/e2e/paths/03-worker/04_time_control.spec.js index eb1417ba9..5f64aa6ce 100644 --- a/e2e/paths/03-worker/04_time_control.spec.js +++ b/e2e/paths/03-worker/04_time_control.spec.js @@ -27,7 +27,7 @@ describe('Worker time control path', () => { date.setMonth(date.getMonth() + 1); let month = date.toLocaleString('default', {month: 'long'}); - await page.click(selectors.workerTimeControl.nextMonthButton); + await page.waitToClick(selectors.workerTimeControl.nextMonthButton); let result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText'); expect(result).toContain(month); @@ -36,7 +36,7 @@ describe('Worker time control path', () => { date.setDate(1); month = date.toLocaleString('default', {month: 'long'}); - await page.click(selectors.workerTimeControl.previousMonthButton); + await page.waitToClick(selectors.workerTimeControl.previousMonthButton); result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText'); expect(result).toContain(month); @@ -49,7 +49,7 @@ describe('Worker time control path', () => { await page.loginAndModule('salesBoss', 'worker'); await page.goto(`http://localhost:5000/#!/worker/${hankPymId}/time-control?timestamp=${timestamp}`); - await page.click(selectors.workerTimeControl.secondWeekDay); + await page.waitToClick(selectors.workerTimeControl.secondWeekDay); result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText'); diff --git a/e2e/paths/03-worker/06_create.spec.js b/e2e/paths/03-worker/06_create.spec.js index 5f6f5cf9f..98e67edbf 100644 --- a/e2e/paths/03-worker/06_create.spec.js +++ b/e2e/paths/03-worker/06_create.spec.js @@ -26,7 +26,6 @@ describe('Worker create path', () => { await page.write(selectors.workerCreate.street, 'S/ Doomstadt'); await page.write(selectors.workerCreate.email, 'doctorDoom@marvel.com'); await page.write(selectors.workerCreate.iban, 'ES9121000418450200051332'); - await page.autocompleteSearch(selectors.workerCreate.switft, 'BBKKESMMMMM'); // should check for autocompleted worker code and worker user name const workerCode = await page diff --git a/e2e/paths/04-item/10_item_log.spec.js b/e2e/paths/04-item/10_item_log.spec.js index 46979a761..6a7bd7ae2 100644 --- a/e2e/paths/04-item/10_item_log.spec.js +++ b/e2e/paths/04-item/10_item_log.spec.js @@ -48,14 +48,14 @@ describe('Item log path', () => { await page.accessToSection('item.card.log'); }); - it(`should confirm the log is showing 5 entries`, async() => { + it(`should confirm the log is showing 4 entries`, async() => { await page.waitForSelector(selectors.itemLog.anyLineCreated); const anyLineCreatedCount = await page.countElement(selectors.itemLog.anyLineCreated); - expect(anyLineCreatedCount).toEqual(5); + expect(anyLineCreatedCount).toEqual(4); }); - it(`should confirm the log is showing the intrastat for the created item`, async() => { + xit(`should confirm the log is showing the intrastat for the created item`, async() => { const fifthLineCreatedProperty = await page .waitToGetProperty(selectors.itemLog.fifthLineCreatedProperty, 'innerText'); diff --git a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js index 36161ae1d..f9b520981 100644 --- a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js +++ b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js @@ -197,6 +197,7 @@ describe('Ticket Edit sale path', () => { }); it('should check in the history that logs has been added', async() => { + pending('https://redmine.verdnatura.es/issues/5455'); await page.reload({waitUntil: ['networkidle0', 'domcontentloaded']}); await page.waitToClick(selectors.ticketSales.firstSaleHistoryButton); await page.waitForSelector(selectors.ticketSales.firstSaleHistory); diff --git a/e2e/paths/05-ticket/21_future.spec.js b/e2e/paths/05-ticket/21_future.spec.js index 2b8057247..626056958 100644 --- a/e2e/paths/05-ticket/21_future.spec.js +++ b/e2e/paths/05-ticket/21_future.spec.js @@ -54,7 +54,7 @@ describe('Ticket Future path', () => { it('should search with the origin IPT', async() => { await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal'); + await page.autocompleteSearch(selectors.ticketFuture.ipt, 'H'); await page.waitToClick(selectors.ticketFuture.submit); expect(httpRequest).toContain('ipt=H'); @@ -65,7 +65,7 @@ describe('Ticket Future path', () => { await page.clearInput(selectors.ticketFuture.ipt); - await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'Horizontal'); + await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'H'); await page.waitToClick(selectors.ticketFuture.submit); expect(httpRequest).toContain('futureIpt=H'); @@ -108,7 +108,7 @@ describe('Ticket Future path', () => { it('should search in smart-table with an IPT Destination', async() => { await page.waitToClick(selectors.ticketFuture.tableButtonSearch); - await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'Horizontal'); + await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'H'); expect(httpRequest).toContain('futureIpt'); await page.waitToClick(selectors.ticketFuture.tableButtonSearch); diff --git a/e2e/paths/05-ticket/22_advance.spec.js b/e2e/paths/05-ticket/22_advance.spec.js index f8442bf12..15f9dd5bb 100644 --- a/e2e/paths/05-ticket/22_advance.spec.js +++ b/e2e/paths/05-ticket/22_advance.spec.js @@ -54,7 +54,7 @@ describe('Ticket Advance path', () => { it('should search with the origin IPT', async() => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'Horizontal'); + await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'H'); await page.waitToClick(selectors.ticketAdvance.submit); expect(httpRequest).toContain('futureIpt=H'); @@ -66,7 +66,7 @@ describe('Ticket Advance path', () => { it('should search with the destination IPT', async() => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal'); + await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'H'); await page.waitToClick(selectors.ticketAdvance.submit); expect(httpRequest).toContain('ipt=H'); @@ -78,7 +78,7 @@ describe('Ticket Advance path', () => { it('should search in smart-table with an IPT Origin', async() => { await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'Vertical'); + await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'V'); expect(httpRequest).toContain('futureIpt'); @@ -89,7 +89,7 @@ describe('Ticket Advance path', () => { it('should search in smart-table with an IPT Destination', async() => { await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'Vertical'); + await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'V'); expect(httpRequest).toContain('ipt'); diff --git a/e2e/paths/10-travel/02_basic_data_and_log.spec.js b/e2e/paths/10-travel/02_basic_data_and_log.spec.js index 341b38f59..bffcb8642 100644 --- a/e2e/paths/10-travel/02_basic_data_and_log.spec.js +++ b/e2e/paths/10-travel/02_basic_data_and_log.spec.js @@ -89,11 +89,13 @@ describe('Travel basic data path', () => { }); it('should navigate to the travel logs', async() => { + pending('https://redmine.verdnatura.es/issues/5455'); await page.accessToSection('travel.card.log'); await page.waitForState('travel.card.log'); }); it('should check the 1st log contains details from the changes made', async() => { + pending('https://redmine.verdnatura.es/issues/5455'); const result = await page.waitToGetProperty(selectors.travelLog.firstLogFirstTD, 'innerText'); expect(result).toContain('new reference!'); diff --git a/modules/claim/back/methods/claim-state/isEditable.js b/modules/claim/back/methods/claim-state/isEditable.js index 2d0a8dc44..ad51d543a 100644 --- a/modules/claim/back/methods/claim-state/isEditable.js +++ b/modules/claim/back/methods/claim-state/isEditable.js @@ -26,13 +26,13 @@ module.exports = Self => { if (typeof options == 'object') Object.assign(myOptions, options); - - const state = await models.ClaimState.findById(id, { - include: { - relation: 'writeRole' - } - }, myOptions); - const roleWithGrants = state && state.writeRole().name; - return await models.Account.hasRole(userId, roleWithGrants, myOptions); + + const state = await models.ClaimState.findById(id, { + include: { + relation: 'writeRole' + } + }, myOptions); + const roleWithGrants = state && state.writeRole().name; + return await models.Account.hasRole(userId, roleWithGrants, myOptions); }; }; diff --git a/modules/claim/back/methods/claim/logs.js b/modules/claim/back/methods/claim/logs.js index c7e69680b..f47513e9e 100644 --- a/modules/claim/back/methods/claim/logs.js +++ b/modules/claim/back/methods/claim/logs.js @@ -1,7 +1,7 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const buildFilter = require('vn-loopback/util/filter').buildFilter; -const {mergeFilters, mergeWhere} = require('vn-loopback/util/filter'); +const { mergeFilters, mergeWhere } = require('vn-loopback/util/filter'); module.exports = Self => { Self.remoteMethodCtx('logs', { @@ -12,27 +12,27 @@ module.exports = Self => { arg: 'id', type: 'Number', description: 'The claim id', - http: {source: 'path'} + http: { source: 'path' } }, { arg: 'filter', type: 'object', - http: {source: 'query'} + http: { source: 'query' } }, { arg: 'search', type: 'string', - http: {source: 'query'} + http: { source: 'query' } }, { arg: 'userFk', type: 'number', - http: {source: 'query'} + http: { source: 'query' } }, { arg: 'created', type: 'date', - http: {source: 'query'} + http: { source: 'query' } }, ], returns: { @@ -45,7 +45,7 @@ module.exports = Self => { } }); - Self.logs = async(ctx, id, filter, options) => { + Self.logs = async (ctx, id, filter, options) => { const conn = Self.dataSource.connector; const args = ctx.args; const myOptions = {}; @@ -56,25 +56,25 @@ module.exports = Self => { let where = buildFilter(args, (param, value) => { switch (param) { - case 'search': - return { - or: [ - {changedModel: {like: `%${value}%`}}, - {oldInstance: {like: `%${value}%`}} - ] - }; - case 'userFk': - return {'cl.userFk': value}; - case 'created': - value.setHours(0, 0, 0, 0); - to = new Date(value); - to.setHours(23, 59, 59, 999); + case 'search': + return { + or: [ + { changedModel: { like: `%${value}%` } }, + { oldInstance: { like: `%${value}%` } } + ] + }; + case 'userFk': + return { 'cl.userFk': value }; + case 'created': + value.setHours(0, 0, 0, 0); + to = new Date(value); + to.setHours(23, 59, 59, 999); - return {creationDate: {between: [value, to]}}; + return { creationDate: { between: [value, to] } }; } }); - where = mergeWhere(where, {['cl.originFk']: id}); - filter = mergeFilters(args.filter, {where}); + where = mergeWhere(where, { ['cl.originFk']: id }); + filter = mergeFilters(args.filter, { where }); const stmts = []; @@ -102,8 +102,8 @@ module.exports = Self => { const logs = []; for (const row of result) { const changes = []; - const oldInstance = JSON.parse(row.oldInstance); - const newInstance = JSON.parse(row.newInstance); + const oldInstance = JSON.parse(row.oldInstance) || {}; + const newInstance = JSON.parse(row.newInstance) || {}; const mergedProperties = [...Object.keys(oldInstance), ...Object.keys(newInstance)]; const properties = new Set(mergedProperties); for (const property of properties) { diff --git a/modules/claim/back/methods/claim/specs/regularizeClaim.spec.js b/modules/claim/back/methods/claim/specs/regularizeClaim.spec.js index bf26d2255..276843c32 100644 --- a/modules/claim/back/methods/claim/specs/regularizeClaim.spec.js +++ b/modules/claim/back/methods/claim/specs/regularizeClaim.spec.js @@ -1,4 +1,5 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('claim regularizeClaim()', () => { const userId = 18; @@ -39,6 +40,20 @@ describe('claim regularizeClaim()', () => { return await models.ClaimEnd.create(claimEnds, options); } + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it('should send a chat message with value "Trash" and then change claim state to resolved', async() => { const tx = await models.Claim.beginTransaction({}); diff --git a/modules/claim/back/models/claim.json b/modules/claim/back/models/claim.json index cd5b767e4..4b26720e5 100644 --- a/modules/claim/back/models/claim.json +++ b/modules/claim/back/models/claim.json @@ -82,6 +82,11 @@ "type": "hasMany", "model": "ClaimDms", "foreignKey": "claimFk" + }, + "lines": { + "type": "hasMany", + "model": "ClaimBeginning", + "foreignKey": "claimFk" } } } diff --git a/modules/claim/front/detail/index.js b/modules/claim/front/detail/index.js index 833519579..56f39e074 100644 --- a/modules/claim/front/detail/index.js +++ b/modules/claim/front/detail/index.js @@ -151,7 +151,7 @@ class Controller extends Section { isClaimEditable() { if (!this.claim) return; - this.$http.get(`ClaimStates/${this.claim.id}/isEditable`).then(res => { + this.$http.get(`ClaimStates/${this.claim.claimStateFk}/isEditable`).then(res => { this.isRewritable = res.data; }); } diff --git a/modules/claim/front/detail/index.spec.js b/modules/claim/front/detail/index.spec.js index 8f3049339..1ef779fd7 100644 --- a/modules/claim/front/detail/index.spec.js +++ b/modules/claim/front/detail/index.spec.js @@ -22,7 +22,8 @@ describe('claim', () => { controller = $componentController('vnClaimDetail', {$element, $scope}); controller.claim = { ticketFk: 1, - id: 2} + id: 2, + claimStateFk: 2} ; controller.salesToClaim = [{saleFk: 1}, {saleFk: 2}]; controller.salesClaimed = [{id: 1, sale: {}}]; diff --git a/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js b/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js index 86ed9dddc..99d2df67b 100644 --- a/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js +++ b/modules/entry/back/methods/entry/specs/editLatestBuys.spec.js @@ -1,6 +1,22 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('Buy editLatestsBuys()', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it('should change the value of a given column for the selected buys', async() => { const tx = await models.Buy.beginTransaction({}); const options = {transaction: tx}; diff --git a/modules/entry/back/models/buy.json b/modules/entry/back/models/buy.json index 8e36d0eef..de2ddffd6 100644 --- a/modules/entry/back/models/buy.json +++ b/modules/entry/back/models/buy.json @@ -3,7 +3,8 @@ "base": "Loggable", "log": { "model": "EntryLog", - "relation": "entry" + "relation": "entry", + "grabUser": true }, "options": { "mysql": { @@ -70,4 +71,4 @@ "foreignKey": "packageFk" } } -} \ No newline at end of file +} diff --git a/modules/entry/back/models/entry.json b/modules/entry/back/models/entry.json index 6c5e1b7d3..5aa175758 100644 --- a/modules/entry/back/models/entry.json +++ b/modules/entry/back/models/entry.json @@ -2,7 +2,8 @@ "name": "Entry", "base": "Loggable", "log": { - "model":"EntryLog" + "model":"EntryLog", + "grabUser": true }, "options": { "mysql": { diff --git a/modules/item/back/methods/fixed-price/specs/upsertFixedPrice.spec.js b/modules/item/back/methods/fixed-price/specs/upsertFixedPrice.spec.js index 5a47de6bf..86f73122d 100644 --- a/modules/item/back/methods/fixed-price/specs/upsertFixedPrice.spec.js +++ b/modules/item/back/methods/fixed-price/specs/upsertFixedPrice.spec.js @@ -1,4 +1,5 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('upsertFixedPrice()', () => { const now = Date.vnNew(); @@ -7,6 +8,17 @@ describe('upsertFixedPrice()', () => { beforeAll(async() => { originalFixedPrice = await models.FixedPrice.findById(fixedPriceId); + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); }); it(`should toggle the hasMinPrice boolean if there's a minPrice and update the rest of the data`, async() => { diff --git a/modules/item/back/methods/item/specs/clone.spec.js b/modules/item/back/methods/item/specs/clone.spec.js index 1f4a87ac1..01210677e 100644 --- a/modules/item/back/methods/item/specs/clone.spec.js +++ b/modules/item/back/methods/item/specs/clone.spec.js @@ -1,7 +1,21 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('item clone()', () => { let nextItemId; + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); beforeEach(async() => { let query = `SELECT i1.id + 1 as id FROM vn.item i1 diff --git a/modules/item/back/methods/item/specs/new.spec.js b/modules/item/back/methods/item/specs/new.spec.js index e34ab2cf5..a1c741649 100644 --- a/modules/item/back/methods/item/specs/new.spec.js +++ b/modules/item/back/methods/item/specs/new.spec.js @@ -1,6 +1,21 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('item new()', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it('should create a new item, adding the name as a tag', async() => { const tx = await models.Item.beginTransaction({}); const options = {transaction: tx}; diff --git a/modules/item/back/methods/item/specs/regularize.spec.js b/modules/item/back/methods/item/specs/regularize.spec.js index ea0cdfa5a..e7df9a003 100644 --- a/modules/item/back/methods/item/specs/regularize.spec.js +++ b/modules/item/back/methods/item/specs/regularize.spec.js @@ -1,6 +1,21 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('regularize()', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 18}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it('should create a new ticket and add a line', async() => { const tx = await models.Item.beginTransaction({}); const options = {transaction: tx}; diff --git a/modules/item/back/models/item.json b/modules/item/back/models/item.json index 10300f7a1..d6b3c27ad 100644 --- a/modules/item/back/models/item.json +++ b/modules/item/back/models/item.json @@ -3,7 +3,8 @@ "base": "Loggable", "log": { "model": "ItemLog", - "showField": "id" + "showField": "id", + "grabUser": true }, "options": { "mysql": { @@ -220,4 +221,4 @@ } } } -} \ No newline at end of file +} diff --git a/modules/monitor/back/methods/sales-monitor/salesFilter.js b/modules/monitor/back/methods/sales-monitor/salesFilter.js index 881fc637a..484f3d0b1 100644 --- a/modules/monitor/back/methods/sales-monitor/salesFilter.js +++ b/modules/monitor/back/methods/sales-monitor/salesFilter.js @@ -295,11 +295,26 @@ module.exports = Self => { risk = t.debt + t.credit, totalProblems = totalProblems + 1 `); + stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getWarnings'); + stmt = new ParameterizedSQL(` - SELECT t.*, tp.*, - ((tp.risk) + cc.riskTolerance < 0) AS hasHighRisk + CREATE TEMPORARY TABLE tmp.sale_getWarnings + (INDEX (ticketFk, agencyModeFk)) + ENGINE = MEMORY + SELECT f.id ticketFk, f.agencyModeFk + FROM tmp.filter f`); + stmts.push(stmt); + + stmts.push('CALL ticket_getWarnings()'); + + stmt = new ParameterizedSQL(` + SELECT t.*, + tp.*, + ((tp.risk) + cc.riskTolerance < 0) AS hasHighRisk, + tw.* FROM tmp.tickets t LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = t.id + LEFT JOIN tmp.ticket_warnings tw ON tw.ticketFk = t.id JOIN clientConfig cc`); const hasProblems = args.problems; @@ -387,6 +402,8 @@ module.exports = Self => { tmp.filter, tmp.ticket_problems, tmp.sale_getProblems, + tmp.sale_getWarnings, + tmp.ticket_warnings, tmp.risk`); const sql = ParameterizedSQL.join(stmts, ';'); diff --git a/modules/monitor/front/index/locale/es.yml b/modules/monitor/front/index/locale/es.yml index 126528caa..f114a2259 100644 --- a/modules/monitor/front/index/locale/es.yml +++ b/modules/monitor/front/index/locale/es.yml @@ -12,4 +12,5 @@ Theoretical: Teórica Practical: Práctica Preparation: Preparación Auto-refresh: Auto-refresco -Toggle auto-refresh every 2 minutes: Conmuta el refresco automático cada 2 minutos \ No newline at end of file +Toggle auto-refresh every 2 minutes: Conmuta el refresco automático cada 2 minutos +Is fragile: Es frágil diff --git a/modules/monitor/front/index/tickets/index.html b/modules/monitor/front/index/tickets/index.html index b8559154e..539d4b3cb 100644 --- a/modules/monitor/front/index/tickets/index.html +++ b/modules/monitor/front/index/tickets/index.html @@ -19,13 +19,13 @@ Tickets monitor - + - State + Zone @@ -80,7 +81,7 @@ @@ -169,12 +170,20 @@ class="link"> {{ticket.refFk}} - {{ticket.state}} + + + + - Filter by selection - Exclude selection - Remove filter - Remove all filters - Copy value diff --git a/modules/route/back/methods/route/specs/clone.spec.js b/modules/route/back/methods/route/specs/clone.spec.js index 9192854f8..496ae1c89 100644 --- a/modules/route/back/methods/route/specs/clone.spec.js +++ b/modules/route/back/methods/route/specs/clone.spec.js @@ -1,6 +1,22 @@ const app = require('vn-loopback/server/server'); +const LoopBackContext = require('loopback-context'); describe('route clone()', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + const createdDate = Date.vnNew(); it('should throw an error if the amount of ids pased to the clone function do no match the database', async() => { const ids = [996, 997, 998, 999]; diff --git a/modules/route/back/methods/route/specs/updateWorkCenter.spec.js b/modules/route/back/methods/route/specs/updateWorkCenter.spec.js index 5328dc240..baa63f226 100644 --- a/modules/route/back/methods/route/specs/updateWorkCenter.spec.js +++ b/modules/route/back/methods/route/specs/updateWorkCenter.spec.js @@ -1,6 +1,20 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('route updateWorkCenter()', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); const routeId = 1; it('should set the commission work center if the worker has workCenter', async() => { diff --git a/modules/route/back/models/route.json b/modules/route/back/models/route.json index 12b9785db..3b12f4ee6 100644 --- a/modules/route/back/models/route.json +++ b/modules/route/back/models/route.json @@ -2,7 +2,8 @@ "name": "Route", "base": "Loggable", "log": { - "model":"RouteLog" + "model":"RouteLog", + "grabUser": true }, "options": { "mysql": { diff --git a/modules/ticket/back/methods/sale/specs/canEdit.spec.js b/modules/ticket/back/methods/sale/specs/canEdit.spec.js index a6c299321..62f98421a 100644 --- a/modules/ticket/back/methods/sale/specs/canEdit.spec.js +++ b/modules/ticket/back/methods/sale/specs/canEdit.spec.js @@ -1,7 +1,21 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('sale canEdit()', () => { const employeeId = 1; + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); describe('sale editTracked', () => { it('should return true if the role is production regardless of the saleTrackings', async() => { diff --git a/modules/ticket/back/methods/sale/specs/deleteSales.spec.js b/modules/ticket/back/methods/sale/specs/deleteSales.spec.js index 82cf916b3..3d3e06e22 100644 --- a/modules/ticket/back/methods/sale/specs/deleteSales.spec.js +++ b/modules/ticket/back/methods/sale/specs/deleteSales.spec.js @@ -1,6 +1,21 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('sale deleteSales()', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it('should throw an error if the ticket of the given sales is not editable', async() => { const tx = await models.Sale.beginTransaction({}); diff --git a/modules/ticket/back/methods/sale/specs/reserve.spec.js b/modules/ticket/back/methods/sale/specs/reserve.spec.js index 7ab79f9c0..259cb8cd5 100644 --- a/modules/ticket/back/methods/sale/specs/reserve.spec.js +++ b/modules/ticket/back/methods/sale/specs/reserve.spec.js @@ -1,4 +1,5 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('sale reserve()', () => { const ctx = { @@ -9,6 +10,20 @@ describe('sale reserve()', () => { } }; + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + it('should throw an error if the ticket can not be modified', async() => { const tx = await models.Sale.beginTransaction({}); diff --git a/modules/ticket/back/methods/sale/specs/updateConcept.spec.js b/modules/ticket/back/methods/sale/specs/updateConcept.spec.js index 0e7e9bf0f..1b42e7140 100644 --- a/modules/ticket/back/methods/sale/specs/updateConcept.spec.js +++ b/modules/ticket/back/methods/sale/specs/updateConcept.spec.js @@ -1,6 +1,21 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('sale updateConcept()', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + const ctx = {req: {accessToken: {userId: 9}}}; const saleId = 25; diff --git a/modules/ticket/back/methods/sale/specs/updatePrice.spec.js b/modules/ticket/back/methods/sale/specs/updatePrice.spec.js index 51cd2403f..133be8de3 100644 --- a/modules/ticket/back/methods/sale/specs/updatePrice.spec.js +++ b/modules/ticket/back/methods/sale/specs/updatePrice.spec.js @@ -1,6 +1,21 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('sale updatePrice()', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 18}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + const ctx = { req: { accessToken: {userId: 18}, diff --git a/modules/ticket/back/methods/sale/specs/updateQuantity.spec.js b/modules/ticket/back/methods/sale/specs/updateQuantity.spec.js index 53a05cd7e..4778f6b6d 100644 --- a/modules/ticket/back/methods/sale/specs/updateQuantity.spec.js +++ b/modules/ticket/back/methods/sale/specs/updateQuantity.spec.js @@ -1,6 +1,21 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('sale updateQuantity()', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + const ctx = { req: { accessToken: {userId: 9}, diff --git a/modules/ticket/back/methods/ticket/new.js b/modules/ticket/back/methods/ticket/new.js index 597ece3e5..a5d04bc4c 100644 --- a/modules/ticket/back/methods/ticket/new.js +++ b/modules/ticket/back/methods/ticket/new.js @@ -127,19 +127,6 @@ module.exports = Self => { ], myOptions); const ticket = await models.Ticket.findById(result[1][0].newTicketId, null, myOptions); - const cleanInstance = JSON.parse(JSON.stringify(ticket)); - - const logRecord = { - originFk: cleanInstance.id, - userFk: myUserId, - action: 'insert', - changedModel: 'Ticket', - changedModelId: cleanInstance.id, - oldInstance: {}, - newInstance: cleanInstance - }; - - await models.TicketLog.create(logRecord, myOptions); if (tx) await tx.commit(); diff --git a/modules/ticket/back/methods/ticket/specs/addSale.spec.js b/modules/ticket/back/methods/ticket/specs/addSale.spec.js index cfd149511..2e568716a 100644 --- a/modules/ticket/back/methods/ticket/specs/addSale.spec.js +++ b/modules/ticket/back/methods/ticket/specs/addSale.spec.js @@ -1,7 +1,21 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('ticket addSale()', () => { const ticketId = 13; + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); it('should create a new sale for the ticket with id 13', async() => { const tx = await models.Ticket.beginTransaction({}); diff --git a/modules/ticket/back/methods/ticket/specs/merge.spec.js b/modules/ticket/back/methods/ticket/specs/merge.spec.js index 78eb0c8f3..3254e58a8 100644 --- a/modules/ticket/back/methods/ticket/specs/merge.spec.js +++ b/modules/ticket/back/methods/ticket/specs/merge.spec.js @@ -10,11 +10,15 @@ describe('ticket merge()', () => { workerFk: 1 }; - const activeCtx = { - accessToken: {userId: 9}, - }; - - beforeEach(() => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ active: activeCtx }); @@ -35,16 +39,16 @@ describe('ticket merge()', () => { try { const options = {transaction: tx}; - const chatNotificationBeforeMerge = await models.Chat.find(); + const chatNotificationBeforeMerge = await models.Chat.find(null, options); await models.Ticket.merge(ctx, [tickets], options); - const createdTicketLog = await models.TicketLog.find({where: {originFk: tickets.originId}}, options); + const createdTicketLog = await models.TicketLog.find({where: {originFk: tickets.destinationId}}, options); const deletedTicket = await models.Ticket.findOne({where: {id: tickets.originId}}, options); const salesTicketFuture = await models.Sale.find({where: {ticketFk: tickets.destinationId}}, options); - const chatNotificationAfterMerge = await models.Chat.find(); + const chatNotificationAfterMerge = await models.Chat.find(null, options); - expect(createdTicketLog.length).toEqual(2); + expect(createdTicketLog.length).toEqual(1); expect(deletedTicket.isDeleted).toEqual(true); expect(salesTicketFuture.length).toEqual(2); expect(chatNotificationBeforeMerge.length).toEqual(chatNotificationAfterMerge.length - 2); diff --git a/modules/ticket/back/methods/ticket/specs/updateDiscount.spec.js b/modules/ticket/back/methods/ticket/specs/updateDiscount.spec.js index 1f6712087..41de1fd6e 100644 --- a/modules/ticket/back/methods/ticket/specs/updateDiscount.spec.js +++ b/modules/ticket/back/methods/ticket/specs/updateDiscount.spec.js @@ -1,6 +1,20 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('sale updateDiscount()', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); const originalSaleId = 8; it('should throw an error if no sales were selected', async() => { diff --git a/modules/ticket/back/models/sale.json b/modules/ticket/back/models/sale.json index 669b05be6..7b8cf501b 100644 --- a/modules/ticket/back/models/sale.json +++ b/modules/ticket/back/models/sale.json @@ -4,7 +4,8 @@ "log": { "model": "TicketLog", "relation": "ticket", - "showField": "concept" + "showField": "concept", + "grabUser": true }, "options": { "mysql": { diff --git a/modules/ticket/back/models/ticket.json b/modules/ticket/back/models/ticket.json index 1cf2642a5..dabda838a 100644 --- a/modules/ticket/back/models/ticket.json +++ b/modules/ticket/back/models/ticket.json @@ -3,7 +3,8 @@ "base": "Loggable", "log": { "model":"TicketLog", - "showField": "id" + "showField": "id", + "grabUser": true }, "options": { "mysql": { diff --git a/modules/travel/back/methods/travel/extraCommunityFilter.js b/modules/travel/back/methods/travel/extraCommunityFilter.js index 027261c4b..5ee51de8e 100644 --- a/modules/travel/back/methods/travel/extraCommunityFilter.js +++ b/modules/travel/back/methods/travel/extraCommunityFilter.js @@ -130,6 +130,7 @@ module.exports = Self => { SUM(b.stickers) AS stickers, s.id AS cargoSupplierFk, s.nickname AS cargoSupplierNickname, + s.name AS supplierName, CAST(SUM(b.weight * b.stickers) as DECIMAL(10,0)) as loadedKg, CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) as DECIMAL(10,0)) as volumeKg FROM travel t @@ -167,6 +168,7 @@ module.exports = Self => { SUM(b.stickers) AS stickers, e.evaNotes, e.notes, + e.invoiceAmount, CAST(SUM(b.weight * b.stickers) AS DECIMAL(10,0)) as loadedkg, CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) AS DECIMAL(10,0)) as volumeKg FROM tmp.travel tr diff --git a/modules/travel/back/models/travel.json b/modules/travel/back/models/travel.json index c20b7b0bf..7dd9f5bba 100644 --- a/modules/travel/back/models/travel.json +++ b/modules/travel/back/models/travel.json @@ -3,7 +3,8 @@ "base": "Loggable", "log": { "model":"TravelLog", - "showField": "ref" + "showField": "ref", + "grabUser": true }, "options": { "mysql": { diff --git a/modules/travel/front/extra-community/index.html b/modules/travel/front/extra-community/index.html index 376c81aaf..c888f97da 100644 --- a/modules/travel/front/extra-community/index.html +++ b/modules/travel/front/extra-community/index.html @@ -3,7 +3,7 @@ url="Travels/extraCommunityFilter" user-params="::$ctrl.defaultFilter" data="travels" - order="shipped ASC, landed ASC, travelFk, loadPriority, agencyModeFk, evaNotes" + order="landed ASC, shipped ASC, travelFk, loadPriority, agencyModeFk, supplierName, evaNotes" limit="20" auto-load="true"> @@ -48,6 +48,9 @@ Agency + + Amount + Reference @@ -107,6 +110,7 @@ {{::travel.cargoSupplierNickname}} + {{::travel.agencyModeName}} @@ -157,22 +161,15 @@ {{::entry.supplierName}} + {{::entry.invoiceAmount | currency: 'EUR': 2}} - {{::entry.ref}} + {{::entry.invoiceNumber}} {{::entry.stickers}} {{::entry.loadedkg}} {{::entry.volumeKg}} - - - {{::entry.notes}} - - - - - {{::entry.evaNotes}} - - + + diff --git a/print/templates/reports/delivery-note/delivery-note.html b/print/templates/reports/delivery-note/delivery-note.html index eb133c0cd..0be5a30f0 100644 --- a/print/templates/reports/delivery-note/delivery-note.html +++ b/print/templates/reports/delivery-note/delivery-note.html @@ -33,7 +33,7 @@
{{$t('deliveryAddress')}}
-
+

{{address.nickname}}

{{address.street}}
{{address.postalCode}}, {{address.city}} ({{address.province}})
@@ -245,13 +245,8 @@
- + \ No newline at end of file diff --git a/print/templates/reports/invoice/invoice.html b/print/templates/reports/invoice/invoice.html index 2d180878a..7a1ed3319 100644 --- a/print/templates/reports/invoice/invoice.html +++ b/print/templates/reports/invoice/invoice.html @@ -240,13 +240,18 @@
-
+
{{$t('observations')}}
-
{{$t('wireTransfer')}}
-
{{$t('accountNumber', [invoice.iban])}}
+
+
{{$t('wireTransfer')}}
+
{{$t('accountNumber', [invoice.iban])}}
+
+
+ {{ticketObservations}} +
diff --git a/print/templates/reports/invoice/invoice.js b/print/templates/reports/invoice/invoice.js index b135e152b..42988113f 100755 --- a/print/templates/reports/invoice/invoice.js +++ b/print/templates/reports/invoice/invoice.js @@ -21,11 +21,15 @@ module.exports = { const map = new Map(); + this.ticketObservations = ''; for (let ticket of tickets) { ticket.sales = []; map.set(ticket.id, ticket); + + if (ticket.description) this.ticketObservations += ticket.description + ' '; } + this.ticketObservations = this.ticketObservations.trim(); for (let sale of sales) { const ticket = map.get(sale.ticketFk); diff --git a/print/templates/reports/invoice/sql/tickets.sql b/print/templates/reports/invoice/sql/tickets.sql index 162f043e2..a8385599c 100644 --- a/print/templates/reports/invoice/sql/tickets.sql +++ b/print/templates/reports/invoice/sql/tickets.sql @@ -1,8 +1,12 @@ SELECT t.id, t.shipped, - t.nickname -FROM invoiceOut io - JOIN ticket t ON t.refFk = io.ref + t.nickname, + tto.description +FROM invoiceOut io + JOIN ticket t ON t.refFk = io.REF + LEFT JOIN observationType ot ON ot.code = 'invoiceOut' + LEFT JOIN ticketObservation tto ON tto.ticketFk = t.id + AND tto.observationTypeFk = ot.id WHERE t.refFk = ? -ORDER BY t.shipped \ No newline at end of file +ORDER BY t.shipped