diff --git a/db/changes/10190-PostErte/00-ACL.sql b/db/changes/10190-PostErte/00-ACL.sql new file mode 100644 index 0000000000..d19901d481 --- /dev/null +++ b/db/changes/10190-PostErte/00-ACL.sql @@ -0,0 +1 @@ +UPDATE `salix`.`ACL` SET `accessType`='WRITE' WHERE `id`='213'; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index ecf0d37e30..2f36dc584c 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -828,6 +828,12 @@ export default { }, travelThermograph: { add: 'vn-travel-thermograph-index vn-float-button[icon="add"]', + addThermographIcon: 'vn-travel-thermograph-create vn-autocomplete vn-icon[icon="add_circle"]', + newThermographId: 'vn-textfield[ng-model="$ctrl.newThermograph.thermographId"]', + newThermographModel: 'vn-autocomplete[ng-model="$ctrl.newThermograph.model"]', + newThermographWarehouse: 'vn-autocomplete[ng-model="$ctrl.newThermograph.warehouseId"]', + newThermographTemperature: 'vn-autocomplete[ng-model="$ctrl.newThermograph.temperature"]', + createThermographButton: 'form button[response="accept"]', thermographID: 'vn-travel-thermograph-create vn-autocomplete[ng-model="$ctrl.dms.thermographId"]', uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="icon-attach"]', createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr', diff --git a/e2e/paths/10-travel/01_thermograph.spec.js b/e2e/paths/10-travel/01_thermograph.spec.js index 67a62381a9..e7f1e234d9 100644 --- a/e2e/paths/10-travel/01_thermograph.spec.js +++ b/e2e/paths/10-travel/01_thermograph.spec.js @@ -2,6 +2,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; describe('Travel thermograph path', () => { + const thermographName = '7H3-37H3RN4L-FL4M3'; let browser; let page; @@ -26,10 +27,18 @@ describe('Travel thermograph path', () => { await page.waitForState('travel.card.thermograph.create'); }); - it('should select the thermograph and then the file to upload', async() => { + it('should click on the add thermograph icon of the thermograph autocomplete', async() => { + await page.waitToClick(selectors.travelThermograph.addThermographIcon); + await page.write(selectors.travelThermograph.newThermographId, thermographName); + await page.autocompleteSearch(selectors.travelThermograph.newThermographModel, 'TEMPMATE'); + await page.autocompleteSearch(selectors.travelThermograph.newThermographWarehouse, 'Warehouse Two'); + await page.autocompleteSearch(selectors.travelThermograph.newThermographTemperature, 'WARM'); + await page.waitToClick(selectors.travelThermograph.createThermographButton); + }); + + it('should select the file to upload', async() => { let currentDir = process.cwd(); let filePath = `${currentDir}/e2e/dms/ecc/3.jpeg`; - await page.autocompleteSearch(selectors.travelThermograph.thermographID, '138350-0'); const [fileChooser] = await Promise.all([ page.waitForFileChooser(), @@ -38,11 +47,17 @@ describe('Travel thermograph path', () => { await fileChooser.accept([filePath]); await page.waitToClick(selectors.travelThermograph.upload); + + const message = await page.waitForSnackbar(); + const state = await page.getState(); + + expect(message.type).toBe('success'); + expect(state).toBe('travel.card.thermograph.index'); }); - it('should reload the section and check everything was saved', async() => { - let createdThermograph = await page.waitToGetProperty(selectors.travelThermograph.createdThermograph, 'innerText'); + it('should check everything was saved correctly', async() => { + const result = await page.waitToGetProperty(selectors.travelThermograph.createdThermograph, 'innerText'); - expect(createdThermograph).toContain('138350-0'); + expect(result).toContain(thermographName); }); }); diff --git a/loopback/common/methods/vn-model/getEnumValues.js b/loopback/common/methods/vn-model/getEnumValues.js new file mode 100644 index 0000000000..0bc8f8eb6a --- /dev/null +++ b/loopback/common/methods/vn-model/getEnumValues.js @@ -0,0 +1,55 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + /** + * Returns a set of allowed values defined on table scheme + * @param {String} column - Model or Table column name + * @return {Array} - Array of set values + */ + Self.getEnumValues = async function(column) { + let model = this.app.models[this.modelName].definition; + let properties = model.properties; + let tableName = this.modelName; + let schema = null; + + if (model.settings && model.settings.mysql) { + let tableSplit = model.settings.mysql.table.split('.'); + tableName = tableSplit.pop(); + schema = tableSplit.pop() || null; + } + + let property = properties[column]; + + if (!property) + throw new UserError(`Column does not exist`); + + let columnName = property.mysql + ? property.mysql.columnName + : column; + + let columnInfo = await this.rawSql( + `SELECT column_type columnType + FROM information_schema.columns + WHERE table_name = ? + AND table_schema = IFNULL(?, DATABASE()) + AND column_name = ?`, + [tableName, schema, columnName] + ); + + if (!columnInfo || !columnInfo[0]) + throw new UserError(`Cannot fetch column values`); + + let setValues; + setValues = columnInfo[0].columnType + .replace(/^enum\((.*)\)$/i, '$1') + .replace(/'/g, '') + .match(new RegExp(/(\w+)+/, 'ig')); + + let values = []; + setValues.forEach(setValue => { + values.push({value: setValue}); + }); + + return values; + }; +}; diff --git a/loopback/common/methods/vn-model/specs/getEnumValues.spec.js b/loopback/common/methods/vn-model/specs/getEnumValues.spec.js new file mode 100644 index 0000000000..b49a952e4f --- /dev/null +++ b/loopback/common/methods/vn-model/specs/getEnumValues.spec.js @@ -0,0 +1,18 @@ +const app = require('vn-loopback/server/server'); + +describe('Model getEnumValues()', () => { + it('should extend getEnumValues properties to any model passed', () => { + let exampleModel = app.models.TravelThermograph; + + expect(exampleModel.getEnumValues).toBeDefined(); + }); + + it('should return an array of enum values from a given column', async() => { + let result = await app.models.TravelThermograph.getSetValues('temperature'); + + expect(result.length).toEqual(3); + expect(result[0].value).toEqual('enum'); + expect(result[1].value).toEqual('COOL'); + expect(result[2].value).toEqual('WARM'); + }); +}); diff --git a/loopback/common/models/vn-model.js b/loopback/common/models/vn-model.js index d65ca71df0..f56183df2e 100644 --- a/loopback/common/models/vn-model.js +++ b/loopback/common/models/vn-model.js @@ -6,6 +6,7 @@ module.exports = function(Self) { Self.ParameterizedSQL = ParameterizedSQL; require('../methods/vn-model/getSetValues')(Self); + require('../methods/vn-model/getEnumValues')(Self); Object.assign(Self, { setup() { diff --git a/loopback/locale/es.json b/loopback/locale/es.json index eeb18fb73c..d77b6d290f 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -132,5 +132,5 @@ "Distance must be lesser than 1000": "La distancia debe ser inferior a 1000", "This ticket is deleted": "Este ticket está eliminado", "A travel with this data already exists": "Ya existe un travel con estos datos", - "AMOUNT_NOT_MATCH_GROUPING": "AMOUNT_NOT_MATCH_GROUPING" + "This thermograph id already exists": "La id del termógrafo ya existe" } \ No newline at end of file diff --git a/modules/claim/front/descriptor/index.html b/modules/claim/front/descriptor/index.html index 52561b1d04..dcd1032470 100644 --- a/modules/claim/front/descriptor/index.html +++ b/modules/claim/front/descriptor/index.html @@ -2,11 +2,11 @@ module="claim" description="$ctrl.claim.client.name"> - Show Pickup order - + diff --git a/modules/claim/front/descriptor/index.js b/modules/claim/front/descriptor/index.js index ea7784f72d..5b09b18861 100644 --- a/modules/claim/front/descriptor/index.js +++ b/modules/claim/front/descriptor/index.js @@ -12,7 +12,7 @@ class Controller extends Descriptor { showPickupOrder() { this.showReport('claim-pickup-order', { - clientId: this.claim.clientFk, + recipientId: this.claim.clientFk, claimId: this.claim.id }); } @@ -20,7 +20,7 @@ class Controller extends Descriptor { sendPickupOrder() { return this.sendEmail('claim-pickup-order', { recipient: this.claim.client.email, - clientId: this.claim.clientFk, + recipientId: this.claim.clientFk, claimId: this.claim.id }); } diff --git a/modules/claim/front/descriptor/index.spec.js b/modules/claim/front/descriptor/index.spec.js index 1a18141ca0..7cdca1b828 100644 --- a/modules/claim/front/descriptor/index.spec.js +++ b/modules/claim/front/descriptor/index.spec.js @@ -23,7 +23,7 @@ describe('Item Component vnClaimDescriptor', () => { controller.showReport = jest.fn(); const params = { - clientId: claim.clientFk, + recipientId: claim.clientFk, claimId: claim.id }; controller.showPickupOrder(); @@ -38,7 +38,7 @@ describe('Item Component vnClaimDescriptor', () => { const params = { recipient: claim.client.email, - clientId: claim.clientFk, + recipientId: claim.clientFk, claimId: claim.id }; controller.sendPickupOrder(); diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index 417370e9ea..cf3ded2f8c 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -257,7 +257,7 @@ module.exports = Self => { if (!instance.email) return; const params = { authorization: authorization, - clientId: instance.id, + recipientId: instance.id, recipient: instance.email }; await request.get(`${origin}/api/email/payment-update`, { diff --git a/modules/client/front/descriptor/index.js b/modules/client/front/descriptor/index.js index 9948eab432..d079b38dad 100644 --- a/modules/client/front/descriptor/index.js +++ b/modules/client/front/descriptor/index.js @@ -42,7 +42,7 @@ class Controller extends Descriptor { onConsumerReportAccept() { this.showReport('campaign-metrics', { - clientId: this.id, + recipientId: this.id, from: this.from, to: this.to, }); diff --git a/modules/client/front/sample/create/index.js b/modules/client/front/sample/create/index.js index bfb0fd2873..d1dfd3ff52 100644 --- a/modules/client/front/sample/create/index.js +++ b/modules/client/front/sample/create/index.js @@ -61,7 +61,7 @@ class Controller extends Section { send(isPreview, cb) { const sampleType = this.$.sampleType.selection; const params = { - clientId: this.$params.id, + recipientId: this.$params.id, recipient: this.clientSample.recipient }; diff --git a/modules/client/front/sample/create/index.spec.js b/modules/client/front/sample/create/index.spec.js index 6acf9e9602..af7f2f3ff8 100644 --- a/modules/client/front/sample/create/index.spec.js +++ b/modules/client/front/sample/create/index.spec.js @@ -68,7 +68,7 @@ describe('Client', () => { code: 'MyReport' }; controller.clientSample = { - clientId: 101 + recipientId: 101 }; controller.send(false, () => {}); @@ -81,7 +81,7 @@ describe('Client', () => { controller.$.sampleType.selection = null; controller.clientSample = { - clientId: 101, + recipientId: 101, recipient: 'client@email.com' }; @@ -98,7 +98,7 @@ describe('Client', () => { code: 'MyReport' }; controller.clientSample = { - clientId: 101, + recipientId: 101, recipient: 'client@email.com' }; @@ -113,11 +113,11 @@ describe('Client', () => { code: 'MyReport' }; controller.clientSample = { - clientId: 101, + recipientId: 101, recipient: 'client@email.com' }; const expectedParams = { - clientId: 101, + recipientId: 101, recipient: 'client@email.com' }; const serializedParams = $httpParamSerializer(expectedParams); @@ -133,12 +133,12 @@ describe('Client', () => { code: 'MyReport' }; controller.clientSample = { - clientId: 101, + recipientId: 101, recipient: 'client@email.com', companyFk: 442 }; const expectedParams = { - clientId: 101, + recipientId: 101, recipient: 'client@email.com', companyId: 442 }; diff --git a/modules/entry/front/descriptor/index.js b/modules/entry/front/descriptor/index.js index 81b7946d19..c84d0144d0 100644 --- a/modules/entry/front/descriptor/index.js +++ b/modules/entry/front/descriptor/index.js @@ -37,7 +37,6 @@ class Controller extends Descriptor { showEntryReport() { this.showReport('entry-order', { - clientId: this.vnConfig.storage.currentUserWorkerId, entryId: this.entry.id }); } diff --git a/modules/item/back/methods/item/getSummary.js b/modules/item/back/methods/item/getSummary.js index 4fb9d9ed17..fd52951d7d 100644 --- a/modules/item/back/methods/item/getSummary.js +++ b/modules/item/back/methods/item/getSummary.js @@ -22,6 +22,7 @@ module.exports = Self => { Self.getSummary = async id => { let promises = []; let summary = {}; + const models = Self.app.models; // Item basic data and taxes let filter = { @@ -66,7 +67,7 @@ module.exports = Self => { } ] }; - promises.push(Self.app.models.Item.find(filter)); + promises.push(models.Item.find(filter)); // Tags filter = { @@ -78,21 +79,21 @@ module.exports = Self => { relation: 'tag' } }; - promises.push(Self.app.models.ItemTag.find(filter)); + promises.push(models.ItemTag.find(filter)); // Botanical filter = { where: {itemFk: id}, include: [{relation: 'genus'}, {relation: 'specie'}] }; - promises.push(Self.app.models.ItemBotanical.find(filter)); + promises.push(models.ItemBotanical.find(filter)); // Niches filter = { where: {itemFk: id}, include: {relation: 'warehouse'} }; - promises.push(Self.app.models.ItemNiche.find(filter)); + promises.push(models.ItemNiche.find(filter)); let res = await Promise.all(promises); @@ -101,15 +102,10 @@ module.exports = Self => { [summary.botanical] = res[2]; summary.niches = res[3]; - // Visible Avaible - let query = ` - CALL vn.item_getVisibleAvailable(?,curdate(),?,?)`; + res = await models.Item.getVisibleAvailable(summary.item.id, summary.item.itemType().warehouseFk); - let options = [summary.item.id, summary.item.itemType().warehouseFk, false]; - [res] = await Self.rawSql(query, options); - - summary.available = res[0].available ? res[0].available : '-'; - summary.visible = res[0].visible ? res[0].visible : '-'; + summary.available = res.available; + summary.visible = res.visible; return summary; }; }; diff --git a/modules/item/back/methods/item/getVisibleAvailable.js b/modules/item/back/methods/item/getVisibleAvailable.js index 7f0855740e..0dd5787330 100644 --- a/modules/item/back/methods/item/getVisibleAvailable.js +++ b/modules/item/back/methods/item/getVisibleAvailable.js @@ -1,3 +1,4 @@ +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; module.exports = Self => { Self.remoteMethod('getVisibleAvailable', { description: 'Returns visible and available for params', @@ -11,6 +12,11 @@ module.exports = Self => { arg: 'warehouseFk', type: 'Number', required: true, + }, + { + arg: 'dated', + type: 'Date', + required: false, }], returns: { type: ['object'], @@ -22,15 +28,35 @@ module.exports = Self => { } }); - Self.getVisibleAvailable = async(id, warehouseFk) => { - let query = ` - CALL vn.item_getVisibleAvailable(?,curdate(),?,?)`; + Self.getVisibleAvailable = async(id, warehouseFk, dated = new Date()) => { + let stmts = []; - let options = [id, warehouseFk, false]; - [res] = await Self.rawSql(query, options); + stmts.push(new ParameterizedSQL( + 'CALL cache.available_refresh(@availableCalc, FALSE, ?, ?)', [ + warehouseFk, + dated + ] + )); + stmts.push(new ParameterizedSQL( + 'CALL cache.visible_refresh(@visibleCalc, FALSE,?)', [ + warehouseFk + ] + )); + const visibleIndex = stmts.push(new ParameterizedSQL( + 'SELECT visible FROM cache.visible WHERE calc_id = @visibleCalc AND item_id = ?', [ + id + ] + )) - 1; + const availableIndex = stmts.push(new ParameterizedSQL( + 'SELECT available FROM cache.available WHERE calc_id = @availableCalc AND item_id = ?', [ + id + ] + )) - 1; + const sql = ParameterizedSQL.join(stmts, ';'); + let res = await Self.rawStmt(sql); return { - available: res[0].available, - visible: res[0].visible}; + available: res[availableIndex][0] ? res[availableIndex][0].available : 0, + visible: res[visibleIndex][0] ? res[visibleIndex][0].visible : 0}; }; }; diff --git a/modules/item/back/methods/item/regularize.js b/modules/item/back/methods/item/regularize.js index bfbc1e28cc..bd908c2b78 100644 --- a/modules/item/back/methods/item/regularize.js +++ b/modules/item/back/methods/item/regularize.js @@ -61,13 +61,9 @@ module.exports = Self => { }, options); } - let query = ` - CALL vn.item_getVisibleAvailable(?,curdate(),?,?)`; + res = await models.Item.getVisibleAvailable(itemFk, warehouseFk); - let params = [itemFk, warehouseFk, true]; - let [res] = await Self.rawSql(query, params, options); - - let newQuantity = res[0].visible - quantity; + let newQuantity = res.visible - quantity; await models.Sale.create({ ticketFk: ticketFk, diff --git a/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js b/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js new file mode 100644 index 0000000000..77e6cea8f2 --- /dev/null +++ b/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js @@ -0,0 +1,33 @@ +const app = require('vn-loopback/server/server'); + +describe('item getVisibleAvailable()', () => { + it('should check available visible for today', async() => { + const itemFk = 1; + const warehouseFk = 1; + const dated = new Date(); + let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk, dated); + + expect(result.available).toEqual(187); + expect(result.visible).toEqual(92); + }); + + it('should check available visible for no dated', async() => { + const itemFk = 1; + const warehouseFk = 1; + let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk); + + expect(result.available).toEqual(187); + expect(result.visible).toEqual(92); + }); + + it('should check available visible for yesterday', async() => { + const itemFk = 1; + const warehouseFk = 1; + let dated = new Date(); + dated.setDate(dated.getDate() - 1); + let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk, dated); + + expect(result.available).toEqual(0); + expect(result.visible).toEqual(92); + }); +}); diff --git a/modules/item/back/methods/item/specs/regularize.spec.js b/modules/item/back/methods/item/specs/regularize.spec.js index b285c15e15..d34dca25f4 100644 --- a/modules/item/back/methods/item/specs/regularize.spec.js +++ b/modules/item/back/methods/item/specs/regularize.spec.js @@ -14,13 +14,8 @@ describe('regularize()', () => { it('should create a new ticket and add a line', async() => { let ctx = {req: {accessToken: {userId: 18}}}; - - let query = `CALL vn.item_getVisibleAvailable(?,curdate(),?,?)`; - - let options = [itemFk, warehouseFk, true]; - - let [res] = await app.models.Item.rawSql(query, options); - let visible = res[0].visible; + let res = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk); + let visible = res.visible; let saleQuantity = visible - 11; let ticketFk = await app.models.Item.regularize(ctx, itemFk, 11, warehouseFk); diff --git a/modules/item/front/descriptor-popover/index.html b/modules/item/front/descriptor-popover/index.html index d4d8035b92..7a401a076b 100644 --- a/modules/item/front/descriptor-popover/index.html +++ b/modules/item/front/descriptor-popover/index.html @@ -1,5 +1,5 @@ - + { expect(controller.item).toEqual(item); }); }); + + describe('updateStock()', () => { + it(`should perform a get query to store the item data into the controller`, () => { + $httpBackend.expectGET(`Items/${item.id}/getCard`).respond(item); + controller.id = item.id; + $httpBackend.flush(); + + expect(controller.item).toEqual(item); + }); + }); }); diff --git a/modules/order/back/methods/order/getSourceValues.js b/modules/order/back/methods/order/getSourceValues.js index da3685c629..5e9f0e6dc6 100644 --- a/modules/order/back/methods/order/getSourceValues.js +++ b/modules/order/back/methods/order/getSourceValues.js @@ -12,7 +12,7 @@ module.exports = Self => { } }); - Self.getSourceValues = async () => { + Self.getSourceValues = async() => { return Self.getSetValues('sourceApp'); }; }; diff --git a/modules/route/front/descriptor/index.js b/modules/route/front/descriptor/index.js index 0fbc3a5e6b..c140350155 100644 --- a/modules/route/front/descriptor/index.js +++ b/modules/route/front/descriptor/index.js @@ -12,19 +12,16 @@ class Controller extends Descriptor { showRouteReport() { this.showReport('driver-route', { - clientId: this.vnConfig.storage.currentUserWorkerId, routeId: this.id }); } sendRouteReport() { - const params = { - recipient: user.emailUser.email, - clientId: this.vnConfig.storage.currentUserWorkerId, + const workerUser = this.route.worker.user; + this.sendEmail('driver-route', { + recipient: workerUser.emailUser.email, routeId: this.id - }; - return this.$http.get(`email/driver-route`, {params}) - .then(() => this.vnApp.showSuccess(this.$t('Report sent'))); + }); } updateVolume() { diff --git a/modules/ticket/back/methods/ticket-request/confirm.js b/modules/ticket/back/methods/ticket-request/confirm.js index fe08794f1c..15050ba008 100644 --- a/modules/ticket/back/methods/ticket-request/confirm.js +++ b/modules/ticket/back/methods/ticket-request/confirm.js @@ -47,14 +47,9 @@ module.exports = Self => { include: {relation: 'ticket'} }, options); - let [[stock]] = await Self.rawSql(`CALL vn.item_getVisibleAvailable(?,?,?,?)`, [ - ctx.args.itemFk, - request.ticket().shipped, - request.ticket().warehouseFk, - false - ], options); + const res = await models.Item.getVisibleAvailable(ctx.args.itemFk, request.ticket().warehouseFk, request.ticket().shipped); - if (stock.available < 0) + if (res.available < 0) throw new UserError(`This item is not available`); if (request.saleFk) { diff --git a/modules/ticket/back/methods/ticket/addSale.js b/modules/ticket/back/methods/ticket/addSale.js index c1081c4be9..c48b04e924 100644 --- a/modules/ticket/back/methods/ticket/addSale.js +++ b/modules/ticket/back/methods/ticket/addSale.js @@ -42,15 +42,9 @@ module.exports = Self => { const item = await models.Item.findById(itemId); const ticket = await models.Ticket.findById(id); - const shouldRefresh = false; - const [[stock]] = await Self.rawSql(`CALL vn.item_getVisibleAvailable(?, ?, ?, ?)`, [ - itemId, - ticket.shipped, - ticket.warehouseFk, - shouldRefresh - ]); + const res = await models.Item.getVisibleAvailable(itemId, ticket.warehouseFk, ticket.shipped); - if (stock.available < quantity) + if (res.available < quantity) throw new UserError(`This item is not available`); const newSale = await models.Sale.create({ diff --git a/modules/ticket/front/descriptor/index.js b/modules/ticket/front/descriptor/index.js index 1b9048bd77..546c5bec76 100644 --- a/modules/ticket/front/descriptor/index.js +++ b/modules/ticket/front/descriptor/index.js @@ -102,15 +102,15 @@ class Controller extends Descriptor { showDeliveryNote() { this.showReport('delivery-note', { - clientId: this.ticket.client.id, + recipientId: this.ticket.client.id, ticketId: this.id, }); } sendDeliveryNote() { return this.sendEmail('delivery-note', { + recipientId: this.ticket.client.id, recipient: this.ticket.client.email, - clientId: this.ticket.client.id, ticketId: this.id }); } diff --git a/modules/ticket/front/summary/index.html b/modules/ticket/front/summary/index.html index 3ea2b7234f..901e089db6 100644 --- a/modules/ticket/front/summary/index.html +++ b/modules/ticket/front/summary/index.html @@ -121,7 +121,7 @@ {{sale.itemFk | zeroFill:6}} diff --git a/modules/travel/back/methods/thermograph/createThermograph.js b/modules/travel/back/methods/thermograph/createThermograph.js new file mode 100644 index 0000000000..bfca208fe7 --- /dev/null +++ b/modules/travel/back/methods/thermograph/createThermograph.js @@ -0,0 +1,60 @@ +module.exports = Self => { + Self.remoteMethod('createThermograph', { + description: 'Creates a new thermograph', + accessType: 'WRITE', + accepts: [{ + arg: 'thermographId', + type: 'String', + description: 'The thermograph id', + required: true + }, { + arg: 'model', + type: 'String', + description: 'The thermograph model', + required: true + }, { + arg: 'temperature', + type: 'String', + description: 'The thermograph temperature', + required: true + }, { + arg: 'warehouseId', + type: 'Number', + description: 'The warehouse id', + required: true + }], + returns: { + type: 'Object', + root: true + }, + http: { + path: `/createThermograph`, + verb: 'POST' + } + }); + + Self.createThermograph = async(thermographId, model, temperature, warehouseId) => { + const models = Self.app.models; + const tx = await Self.beginTransaction({}); + + try { + const options = {transaction: tx}; + const thermograph = await models.Thermograph.create({ + id: thermographId, + model: model + }, options); + + await Self.rawSql(` + INSERT INTO travelThermograph(thermographFk, warehouseFk, temperature, created) + VALUES (?, ?,?, NOW()) + `, [thermograph.id, warehouseId, temperature], options); + + await tx.commit(); + + return thermograph; + } catch (err) { + await tx.rollback(); + throw err; + } + }; +}; diff --git a/modules/travel/back/methods/thermograph/getThermographModels.js b/modules/travel/back/methods/thermograph/getThermographModels.js new file mode 100644 index 0000000000..188c3a5308 --- /dev/null +++ b/modules/travel/back/methods/thermograph/getThermographModels.js @@ -0,0 +1,18 @@ +module.exports = Self => { + Self.remoteMethod('getThermographModels', { + description: 'Gets the thermograph models', + accessType: 'READ', + returns: { + type: ['String'], + root: true + }, + http: { + path: `/getThermographModels`, + verb: 'GET' + } + }); + + Self.getThermographModels = async() => { + return Self.getEnumValues('model'); + }; +}; diff --git a/modules/travel/back/methods/thermograph/specs/createThermograph.spec.js b/modules/travel/back/methods/thermograph/specs/createThermograph.spec.js new file mode 100644 index 0000000000..733b713f03 --- /dev/null +++ b/modules/travel/back/methods/thermograph/specs/createThermograph.spec.js @@ -0,0 +1,49 @@ +const app = require('vn-loopback/server/server'); + +describe('Termograph createThermograph()', () => { + const models = app.models; + const thermographId = '99999-1'; + const model = 'DISPOSABLE'; + const temperature = 'COOL'; + const warehouseId = 1; + let createdThermograph; + + afterAll(async done => { + let travelThermograpToDelete = await models.TravelThermograph.findOne({where: {thermographFk: createdThermograph.id}}); + let thermograpToDelete = await models.Thermograph.findById(createdThermograph.id); + + await travelThermograpToDelete.destroy(); + await thermograpToDelete.destroy(); + + done(); + }); + + it(`should create a thermograph which is saved in both thermograph and travelThermograph`, async() => { + let createdTravelThermograpth = await models.TravelThermograph.findOne({where: {thermographFk: thermographId}}); + + expect(createdTravelThermograpth).toBeNull(); + + createdThermograph = await models.Thermograph.createThermograph(thermographId, model, temperature, warehouseId); + + expect(createdThermograph.id).toEqual(thermographId); + expect(createdThermograph.model).toEqual(model); + + createdTravelThermograpth = await models.TravelThermograph.findOne({where: {thermographFk: thermographId}}); + + expect(createdTravelThermograpth.warehouseFk).toEqual(warehouseId); + expect(createdTravelThermograpth.temperature).toEqual(temperature); + }); + + it(`should not be able to created duplicated entries`, async() => { + let error; + + try { + await models.Thermograph.createThermograph(thermographId, model, temperature, warehouseId); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error.message).toBe('This thermograph id already exists'); + }); +}); diff --git a/modules/travel/back/methods/travel-thermograph/getThermographTemperatures.js b/modules/travel/back/methods/travel-thermograph/getThermographTemperatures.js new file mode 100644 index 0000000000..1d510b5137 --- /dev/null +++ b/modules/travel/back/methods/travel-thermograph/getThermographTemperatures.js @@ -0,0 +1,18 @@ +module.exports = Self => { + Self.remoteMethod('getThermographTemperatures', { + description: 'Gets the thermograph temperatures', + accessType: 'READ', + returns: { + type: ['String'], + root: true + }, + http: { + path: `/getThermographTemperatures`, + verb: 'GET' + } + }); + + Self.getThermographTemperatures = async() => { + return Self.getEnumValues('temperature'); + }; +}; diff --git a/modules/travel/back/models/thermograph.js b/modules/travel/back/models/thermograph.js new file mode 100644 index 0000000000..3f95a06701 --- /dev/null +++ b/modules/travel/back/models/thermograph.js @@ -0,0 +1,12 @@ +let UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + require('../methods/thermograph/createThermograph')(Self); + require('../methods/thermograph/getThermographModels')(Self); + + Self.rewriteDbError(function(err) { + if (err.code === 'ER_DUP_ENTRY') + return new UserError(`This thermograph id already exists`); + return err; + }); +}; diff --git a/modules/travel/back/models/thermograph.json b/modules/travel/back/models/thermograph.json index 421ae43419..2519fffc40 100644 --- a/modules/travel/back/models/thermograph.json +++ b/modules/travel/back/models/thermograph.json @@ -10,10 +10,12 @@ "id": { "type": "String", "id": true, - "description": "Identifier" + "description": "Identifier", + "required": true }, "model": { - "type": "String" + "type": "String", + "required": true } } } diff --git a/modules/travel/back/models/travel-thermograph.js b/modules/travel/back/models/travel-thermograph.js index 0d70edd7e6..a16e68b985 100644 --- a/modules/travel/back/models/travel-thermograph.js +++ b/modules/travel/back/models/travel-thermograph.js @@ -1,4 +1,5 @@ module.exports = Self => { require('../methods/travel-thermograph/allowedContentTypes')(Self); + require('../methods/travel-thermograph/getThermographTemperatures')(Self); }; diff --git a/modules/travel/back/models/travel-thermograph.json b/modules/travel/back/models/travel-thermograph.json index b8f7fa41a1..70ee0de07e 100644 --- a/modules/travel/back/models/travel-thermograph.json +++ b/modules/travel/back/models/travel-thermograph.json @@ -21,10 +21,15 @@ "type": "Date" }, "temperature": { - "type": "String" + "type": "String", + "required": true }, "result": { "type": "String" + }, + "warehouseFk": { + "type": "Number", + "required": true } }, "relations": { diff --git a/modules/travel/front/thermograph/create/index.html b/modules/travel/front/thermograph/create/index.html index 4b1fc8cf4f..0232c1b127 100644 --- a/modules/travel/front/thermograph/create/index.html +++ b/modules/travel/front/thermograph/create/index.html @@ -17,6 +17,18 @@ where="{travelFk: null}" show-field="thermographFk" value-field="thermographFk"> + + {{thermographFk}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/travel/front/thermograph/create/index.js b/modules/travel/front/thermograph/create/index.js index 6c04649911..d398febf1c 100644 --- a/modules/travel/front/thermograph/create/index.js +++ b/modules/travel/front/thermograph/create/index.js @@ -55,6 +55,28 @@ class Controller extends Section { }); } + onAddThermographClick(event) { + const defaultTemperature = 'COOL'; + const defaultModel = 'DISPOSABLE'; + + event.preventDefault(); + this.newThermograph = { + thermographId: this.thermographId, + warehouseId: this.warehouseId, + temperature: defaultTemperature, + model: defaultModel + }; + + this.$.modelsModel.refresh(); + this.$.temperaturesModel.refresh(); + this.$.newThermographDialog.show(); + } + + onNewThermographAccept() { + return this.$http.post(`Thermographs/createThermograph`, this.newThermograph) + .then(res => this.dms.thermographId = res.data.id); + } + onSubmit() { const query = `Travels/${this.travel.id}/createThermograph`; const options = { diff --git a/modules/travel/front/thermograph/create/index.spec.js b/modules/travel/front/thermograph/create/index.spec.js index 58fbe3991f..23976fc96c 100644 --- a/modules/travel/front/thermograph/create/index.spec.js +++ b/modules/travel/front/thermograph/create/index.spec.js @@ -63,5 +63,32 @@ describe('Ticket', () => { expect(controller.allowedContentTypes).toEqual('application/pdf, image/png, image/jpg'); }); }); + + describe('onAddThermographClick()', () => { + it('should call the show() function of the create thermograph dialog', () => { + controller.$.newThermographDialog = {show: jest.fn()}; + controller.$.modelsModel = {refresh: jest.fn()}; + controller.$.temperaturesModel = {refresh: jest.fn()}; + + const event = new Event('click'); + jest.spyOn(event, 'preventDefault'); + + controller.onAddThermographClick(event); + + expect(event.preventDefault).toHaveBeenCalledTimes(1); + expect(controller.$.newThermographDialog.show).toHaveBeenCalledTimes(1); + }); + }); + + describe('onNewThermographAccept()', () => { + it('should set the created thermograph id on to the controller for the autocomplete to use it', () => { + const response = {id: 'the created id'}; + $httpBackend.when('POST', `Thermographs/createThermograph`).respond(response); + controller.onNewThermographAccept(); + $httpBackend.flush(); + + expect(controller.dms.thermographId).toEqual(response.id); + }); + }); }); }); diff --git a/modules/travel/front/thermograph/locale/es.yml b/modules/travel/front/thermograph/locale/es.yml index 9f9be564b7..0e3bc99fc7 100644 --- a/modules/travel/front/thermograph/locale/es.yml +++ b/modules/travel/front/thermograph/locale/es.yml @@ -15,4 +15,6 @@ Add thermograph: Añadir termógrafo Edit thermograph: Editar termógrafo Thermograph deleted: Termógrafo eliminado Thermograph: Termógrafo -Are you sure you want to remove the thermograph?: ¿Seguro que quieres quitar el termógrafo? \ No newline at end of file +New thermograph: Nuevo termógrafo +Are you sure you want to remove the thermograph?: ¿Seguro que quieres quitar el termógrafo? +Identifier: Identificador \ No newline at end of file diff --git a/modules/zone/front/delivery-days/index.spec.js b/modules/zone/front/delivery-days/index.spec.js index 156407420b..db99add2c3 100644 --- a/modules/zone/front/delivery-days/index.spec.js +++ b/modules/zone/front/delivery-days/index.spec.js @@ -61,8 +61,8 @@ describe('Zone Component vnZoneDeliveryDays', () => { expect(controller.$.data).toEqual(expectedData); }); }); - // Petición #2259 cread - xdescribe('onSelection()', () => { + + describe('onSelection()', () => { it('should not call the show popover method if events array is empty', () => { jest.spyOn(controller.$.zoneEvents, 'show'); diff --git a/package-lock.json b/package-lock.json index b46d40dcc5..4a597175a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3244,7 +3244,7 @@ }, "util": { "version": "0.10.3", - "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -4060,7 +4060,7 @@ "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { "cache-base": "^1.0.1", @@ -4577,7 +4577,7 @@ "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { "collection-visit": "^1.0.0", @@ -4754,7 +4754,7 @@ "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -5816,7 +5816,7 @@ "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "integrity": "sha1-HxngwuGqDjJ5fEl5nyg3rGr2nFc=", "requires": { "is-obj": "^1.0.0" } @@ -6751,7 +6751,7 @@ }, "file-loader": { "version": "1.1.11", - "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "dev": true, "requires": { @@ -7918,7 +7918,7 @@ "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { "global-prefix": "^1.0.1", @@ -8500,7 +8500,7 @@ "dependencies": { "es6-promise": { "version": "3.3.1", - "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", "dev": true }, @@ -9579,7 +9579,7 @@ "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "requires": { "isobject": "^3.0.1" @@ -9935,7 +9935,7 @@ "jasmine-spec-reporter": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", - "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", + "integrity": "sha1-HWMq7ANBZwrTJPkrqEtLMrNeniI=", "dev": true, "requires": { "colors": "1.1.2" @@ -11932,7 +11932,7 @@ }, "minimist": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "mississippi": { @@ -12972,7 +12972,7 @@ "dependencies": { "minimist": { "version": "0.0.10", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, @@ -14180,7 +14180,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } @@ -14558,7 +14558,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -14648,7 +14648,7 @@ "dependencies": { "source-map": { "version": "0.4.4", - "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { @@ -15006,7 +15006,7 @@ "snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { "define-property": "^1.0.0", @@ -15057,7 +15057,7 @@ "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { "kind-of": "^3.2.0" @@ -15332,7 +15332,7 @@ "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { "extend-shallow": "^3.0.0" @@ -16409,7 +16409,7 @@ "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "integrity": "sha1-/jZfX3XsntTlaCXgu3bSSrdK+Ds=", "dev": true, "requires": { "nopt": "~1.0.10" diff --git a/print/core/component.js b/print/core/component.js index 836b8c9d9c..4f439f1a92 100644 --- a/print/core/component.js +++ b/print/core/component.js @@ -87,17 +87,29 @@ class Component { return component; } - async render() { + component() { + if (this._component) + return this._component; + const component = this.build(); const i18n = new VueI18n(config.i18n); - const app = new Vue({ + this._component = new Vue({ i18n: i18n, render: h => h(component, { props: this.args }) }); - return renderer.renderToString(app); + return this._component; + } + + /** + * @return {Promise} Rendered component + */ + async render() { + return renderer.renderToString( + this.component() + ); } } diff --git a/print/core/components/attachment/attachment.js b/print/core/components/attachment/attachment.js index 2d4e74cdc5..0f2a6d103d 100755 --- a/print/core/components/attachment/attachment.js +++ b/print/core/components/attachment/attachment.js @@ -15,9 +15,10 @@ module.exports = { const props = this.args; let query = ''; for (let param in props) { - if (query != '') - query += '&'; - query += `${param}=${props[param]}`; + if (!(props[param] instanceof Object)) { + if (query != '') query += '&'; + query += `${param}=${props[param]}`; + } } return query; diff --git a/print/core/email.js b/print/core/email.js index faf744e772..cf6f8b663f 100644 --- a/print/core/email.js +++ b/print/core/email.js @@ -1,9 +1,8 @@ const path = require('path'); const smtp = require('./smtp'); +const config = require('./config'); const Component = require('./component'); const Report = require('./report'); -const db = require('./database'); -const config = require('./config'); if (!process.env.OPENSSL_CONF) process.env.OPENSSL_CONF = '/etc/ssl/'; @@ -20,27 +19,22 @@ class Email extends Component { } async getSubject() { - if (!this.lang) await this.getLang(); - const locale = this.locale.messages; - const userLocale = locale[this.lang]; + const component = await this.component(); + let locale = this.args.auth.locale; - if (!userLocale) { + if (this.args.recipientId) + locale = await component.getLocale(this.args.recipientId); + + const messages = this.locale.messages; + const userTranslations = messages[locale]; + + if (!userTranslations) { const fallbackLocale = config.i18n.fallbackLocale; - return locale[fallbackLocale].subject; + return messages[fallbackLocale].subject; } - return userLocale.subject; - } - - async getLang() { - const clientId = this.args.clientId; - const lang = await db.findOne(` - SELECT lang FROM account.user - WHERE id = ?`, [clientId]).then(rows => { - return rows.lang; - }); - this.lang = lang; + return userTranslations.subject; } async send() { @@ -80,6 +74,7 @@ class Email extends Component { const localeSubject = await this.getSubject(); const options = { to: this.args.recipient, + replyTo: this.args.auth.email, subject: localeSubject, html: rendered, attachments: attachments diff --git a/print/core/mixins/prop-validator.js b/print/core/mixins/prop-validator.js index a73197ebf5..16c71a6db8 100644 --- a/print/core/mixins/prop-validator.js +++ b/print/core/mixins/prop-validator.js @@ -19,8 +19,7 @@ const validator = { throw new Error(`Required properties not found [${required}]`); } }, - props: ['isPreview'] + props: ['isPreview', 'authorization'] }; - Vue.mixin(validator); diff --git a/print/core/mixins/user-locale.js b/print/core/mixins/user-locale.js index f30bc0b280..0e47273340 100644 --- a/print/core/mixins/user-locale.js +++ b/print/core/mixins/user-locale.js @@ -4,28 +4,27 @@ const config = require('../config'); const fallbackLocale = config.i18n.fallbackLocale; const userLocale = { async serverPrefetch() { - if (this.clientId) - this.locale = await this.getLocale(this.clientId); + if (this.auth) + this.$i18n.locale = this.auth.locale; - if (this.locale) - this.$i18n.locale = this.locale; + if (this.recipientId) + this.$i18n.locale = await this.getLocale(this.recipientId); }, methods: { - getLocale(clientId) { + getLocale(recipientId) { return db.findOne(` SELECT IF(u.lang IS NOT NULL, u.lang, LOWER(ct.code)) lang FROM client c JOIN country ct ON ct.id = c.countryFk JOIN account.user u ON u.id = c.id - WHERE c.id = ?`, [clientId]).then(rows => { + WHERE c.id = ?`, [recipientId]).then(rows => { if (rows) return rows.lang; else return fallbackLocale; }); } }, - props: ['clientId'] + props: ['auth', 'recipientId'] }; - Vue.mixin(userLocale); diff --git a/print/core/router.js b/print/core/router.js index 3be6cdd35b..feaea214b9 100644 --- a/print/core/router.js +++ b/print/core/router.js @@ -17,17 +17,32 @@ module.exports = app => { for (let method of methods) paths.push(`/api/${method}/*`); - app.use(paths, async function(request, response, next) { - const authorization = getToken(request); - const query = `SELECT userId, ttl, created - FROM salix.AccessToken WHERE id = ?`; + app.use(paths, async function(req, res, next) { + const token = getToken(req); + const query = `SELECT at.id, at.userId, eu.email, u.lang, at.ttl, at.created + FROM salix.AccessToken at + JOIN account.user u ON u.id = at.userid + JOIN account.emailUser eu ON eu.userFk = u.id + WHERE at.id = ?`; try { - const authToken = await db.findOne(query, [authorization]); + const auth = await db.findOne(query, [token]); - if (!authToken || isTokenExpired(authToken.created, authToken.ttl)) + if (!auth || isTokenExpired(auth.created, auth.ttl)) throw new Error('Invalid authorization token'); + const args = Object.assign({}, req.query); + const props = Object.assign(args, req.body); + props.authorization = auth.id; + + req.args = props; + req.args.auth = { + userId: auth.userId, + token: auth.id, + email: auth.email, + locale: auth.lang + }; + next(); } catch (error) { next(error); @@ -36,12 +51,9 @@ module.exports = app => { function getToken(request) { const headers = request.headers; - const params = request.query; + const queryParams = request.query; - if (headers.authorization) - params.authorization = headers.authorization; - - return headers.authorization || params.authorization; + return headers.authorization || queryParams.authorization; } function isTokenExpired(created, ttl) { diff --git a/print/core/smtp.js b/print/core/smtp.js index b274eafa3c..23d19cabc3 100644 --- a/print/core/smtp.js +++ b/print/core/smtp.js @@ -27,7 +27,7 @@ module.exports = { await db.rawSql(` INSERT INTO vn.mail (sender, replyTo, sent, subject, body, status) VALUES (:recipient, :sender, 1, :subject, :body, :status)`, { - sender: config.app.senderEmail, + sender: options.replyTo, recipient: options.to, subject: options.subject, body: options.text || options.html, diff --git a/print/methods/closure.js b/print/methods/closure.js index 05490609dd..901dce790b 100644 --- a/print/methods/closure.js +++ b/print/methods/closure.js @@ -29,7 +29,7 @@ module.exports = app => { const args = { ticketId: ticket.id, - clientId: ticket.clientFk, + recipientId: ticket.clientFk, recipient: ticket.recipient }; const email = new Email('delivery-note-link', args); diff --git a/print/methods/email.js b/print/methods/email.js index a56798820a..69f880a0a3 100644 --- a/print/methods/email.js +++ b/print/methods/email.js @@ -2,19 +2,11 @@ const Email = require('../core/email'); module.exports = app => { app.get(`/api/email/:name`, async(req, res, next) => { - const args = req.query; - const requiredArgs = ['clientId', 'recipient']; - const argList = requiredArgs.join(','); - const hasRequiredArgs = requiredArgs.every(arg => { - return args[arg]; - }); - try { - if (!hasRequiredArgs) - throw new Error(`Required properties not found [${argList}]`); + const reportName = req.params.name; + const email = new Email(reportName, req.args); - const email = new Email(req.params.name, args); - if (args.isPreview === 'true') { + if (req.args.isPreview === 'true') { const rendered = await email.render(); res.send(rendered); diff --git a/print/methods/report.js b/print/methods/report.js index 117462d9ee..348c05ff39 100644 --- a/print/methods/report.js +++ b/print/methods/report.js @@ -2,20 +2,10 @@ const Report = require('../core/report'); module.exports = app => { app.get(`/api/report/:name`, async(req, res, next) => { - const args = req.query; - const requiredArgs = ['clientId']; - const argList = requiredArgs.join(','); - const hasRequiredArgs = requiredArgs.every(arg => { - return args[arg]; - }); - try { - if (!hasRequiredArgs) - throw new Error(`Required properties not found [${argList}]`); - const reportName = req.params.name; - const fileName = getFileName(reportName, args); - const report = new Report(reportName, args); + const fileName = getFileName(reportName, req.args); + const report = new Report(reportName, req.args); const stream = await report.toPdfStream(); res.setHeader('Content-type', 'application/pdf'); @@ -38,8 +28,7 @@ module.exports = app => { const keys = Object.keys(args); for (let arg of keys) { - // FIXME: #2197 - Remove clientId as a required param - if (arg != 'clientId' && arg.endsWith('Id')) + if (arg.endsWith('Id')) identifiers.push(arg); } diff --git a/print/templates/email/buyer-week-waste/buyer-week-waste.html b/print/templates/email/buyer-week-waste/buyer-week-waste.html index b9ebd61755..9f6b229685 100644 --- a/print/templates/email/buyer-week-waste/buyer-week-waste.html +++ b/print/templates/email/buyer-week-waste/buyer-week-waste.html @@ -1,5 +1,5 @@ - + @@ -43,9 +43,9 @@ {{waste.buyer}} - {{(waste.percentage / 100) | percentage(2, 2, locale)}} - {{waste.dwindle | currency('EUR', locale)}} - {{waste.total | currency('EUR', locale)}} + {{(waste.percentage / 100) | percentage(2, 2, $i18n.locale)}} + {{waste.dwindle | currency('EUR', $i18n.locale)}} + {{waste.total | currency('EUR', $i18n.locale)}} diff --git a/print/templates/email/campaign-metrics/campaign-metrics.html b/print/templates/email/campaign-metrics/campaign-metrics.html index 238d80d4ab..4ba95adb9d 100644 --- a/print/templates/email/campaign-metrics/campaign-metrics.html +++ b/print/templates/email/campaign-metrics/campaign-metrics.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/email/campaign-metrics/campaign-metrics.js b/print/templates/email/campaign-metrics/campaign-metrics.js index cb01ca09e6..51d2ebb444 100755 --- a/print/templates/email/campaign-metrics/campaign-metrics.js +++ b/print/templates/email/campaign-metrics/campaign-metrics.js @@ -10,7 +10,7 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - clientId: { + recipientId: { required: true }, from: { diff --git a/print/templates/email/claim-pickup-order/claim-pickup-order.html b/print/templates/email/claim-pickup-order/claim-pickup-order.html index b003384672..cdde0dd924 100644 --- a/print/templates/email/claim-pickup-order/claim-pickup-order.html +++ b/print/templates/email/claim-pickup-order/claim-pickup-order.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/email/client-welcome/client-welcome.html b/print/templates/email/client-welcome/client-welcome.html index c5f203621b..1d21846d7d 100644 --- a/print/templates/email/client-welcome/client-welcome.html +++ b/print/templates/email/client-welcome/client-welcome.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/email/client-welcome/client-welcome.js b/print/templates/email/client-welcome/client-welcome.js index 35b373bc43..194c133bd6 100755 --- a/print/templates/email/client-welcome/client-welcome.js +++ b/print/templates/email/client-welcome/client-welcome.js @@ -6,7 +6,7 @@ const emailFooter = new Component('email-footer'); module.exports = { name: 'client-welcome', async serverPrefetch() { - this.client = await this.fetchClient(this.clientId); + this.client = await this.fetchClient(this.recipientId); }, methods: { fetchClient(clientId) { @@ -29,7 +29,7 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - clientId: { + recipientId: { required: true } } diff --git a/print/templates/email/delivery-note-link/delivery-note-link.html b/print/templates/email/delivery-note-link/delivery-note-link.html index 28dbc7922c..78fa2c9228 100644 --- a/print/templates/email/delivery-note-link/delivery-note-link.html +++ b/print/templates/email/delivery-note-link/delivery-note-link.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/email/delivery-note/delivery-note.html b/print/templates/email/delivery-note/delivery-note.html index 0ee59a26fe..71de29a3ea 100644 --- a/print/templates/email/delivery-note/delivery-note.html +++ b/print/templates/email/delivery-note/delivery-note.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/email/driver-route/driver-route.html b/print/templates/email/driver-route/driver-route.html index b9d0aeab51..815b28b8c2 100644 --- a/print/templates/email/driver-route/driver-route.html +++ b/print/templates/email/driver-route/driver-route.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/email/letter-debtor-nd/letter-debtor-nd.html b/print/templates/email/letter-debtor-nd/letter-debtor-nd.html index c7a6faebc6..630cce8a26 100644 --- a/print/templates/email/letter-debtor-nd/letter-debtor-nd.html +++ b/print/templates/email/letter-debtor-nd/letter-debtor-nd.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/email/letter-debtor-nd/letter-debtor-nd.js b/print/templates/email/letter-debtor-nd/letter-debtor-nd.js index b2809ac284..be77686084 100755 --- a/print/templates/email/letter-debtor-nd/letter-debtor-nd.js +++ b/print/templates/email/letter-debtor-nd/letter-debtor-nd.js @@ -8,7 +8,7 @@ const attachments = require('./attachments.json'); module.exports = { name: 'letter-debtor-nd', async serverPrefetch() { - this.debtor = await this.fetchDebtor(this.clientId, this.companyId); + this.debtor = await this.fetchDebtor(this.recipientId, this.companyId); if (!this.debtor) throw new Error('Something went wrong'); @@ -40,7 +40,7 @@ module.exports = { authorization: { required: true }, - clientId: { + recipientId: { required: true }, companyId: { diff --git a/print/templates/email/letter-debtor-st/letter-debtor-st.html b/print/templates/email/letter-debtor-st/letter-debtor-st.html index d277d363a4..1fc61a4786 100644 --- a/print/templates/email/letter-debtor-st/letter-debtor-st.html +++ b/print/templates/email/letter-debtor-st/letter-debtor-st.html @@ -1,5 +1,5 @@ - + @@ -23,7 +23,7 @@
-

{{ $t('title') }}

+

{{ $t('title') }} {{$i18n.locale}}

{{ $t('sections.introduction.title') }},

{{ $t('sections.introduction.description') }}

diff --git a/print/templates/email/letter-debtor-st/letter-debtor-st.js b/print/templates/email/letter-debtor-st/letter-debtor-st.js index 61f3c01adb..51ed8b2ff8 100755 --- a/print/templates/email/letter-debtor-st/letter-debtor-st.js +++ b/print/templates/email/letter-debtor-st/letter-debtor-st.js @@ -8,7 +8,7 @@ const attachments = require('./attachments.json'); module.exports = { name: 'letter-debtor-st', async serverPrefetch() { - this.debtor = await this.fetchDebtor(this.clientId, this.companyId); + this.debtor = await this.fetchDebtor(this.recipientId, this.companyId); if (!this.debtor) throw new Error('Something went wrong'); @@ -37,10 +37,7 @@ module.exports = { 'attachment': attachment.build() }, props: { - authorization: { - required: true - }, - clientId: { + recipientId: { required: true }, companyId: { diff --git a/print/templates/email/payment-update/payment-update.html b/print/templates/email/payment-update/payment-update.html index 6bba773081..0838d6efb7 100644 --- a/print/templates/email/payment-update/payment-update.html +++ b/print/templates/email/payment-update/payment-update.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/email/payment-update/payment-update.js b/print/templates/email/payment-update/payment-update.js index 4479deb814..c74cf86940 100755 --- a/print/templates/email/payment-update/payment-update.js +++ b/print/templates/email/payment-update/payment-update.js @@ -6,7 +6,7 @@ const emailFooter = new Component('email-footer'); module.exports = { name: 'payment-update', async serverPrefetch() { - this.payMethod = await this.fetchPayMethod(this.clientId); + this.payMethod = await this.fetchPayMethod(this.recipientId); if (!this.payMethod) throw new Error('Something went wrong'); @@ -34,7 +34,7 @@ module.exports = { 'email-footer': emailFooter.build() }, props: { - clientId: { + recipientId: { required: true } } diff --git a/print/templates/email/printer-setup/printer-setup.html b/print/templates/email/printer-setup/printer-setup.html index 6b295bd8f2..df0b43f0c3 100644 --- a/print/templates/email/printer-setup/printer-setup.html +++ b/print/templates/email/printer-setup/printer-setup.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/email/printer-setup/printer-setup.js b/print/templates/email/printer-setup/printer-setup.js index 86ae0044a2..4aa63587fa 100755 --- a/print/templates/email/printer-setup/printer-setup.js +++ b/print/templates/email/printer-setup/printer-setup.js @@ -8,7 +8,7 @@ const attachments = require('./attachments.json'); module.exports = { name: 'printer-setup', async serverPrefetch() { - this.client = await this.fetchClient(this.clientId); + this.client = await this.fetchClient(this.recipientId); }, data() { return {attachments}; @@ -16,19 +16,19 @@ module.exports = { methods: { fetchClient(clientId) { return db.findOne(` - SELECT - c.id, - u.lang locale, - u.name AS userName, - c.email recipient, - CONCAT(w.lastName, ' ', w.firstName) salesPersonName, - w.phone AS salesPersonPhone, - CONCAT(wu.name, '@verdnatura.es') AS salesPersonEmail - FROM client c - JOIN account.user u ON u.id = c.id - LEFT JOIN worker w ON w.id = c.salesPersonFk - LEFT JOIN account.user wu ON wu.id = w.userFk - WHERE c.id = ?`, [clientId]); + SELECT + c.id, + u.lang locale, + u.name AS userName, + c.email recipient, + CONCAT(w.lastName, ' ', w.firstName) salesPersonName, + w.phone AS salesPersonPhone, + CONCAT(wu.name, '@verdnatura.es') AS salesPersonEmail + FROM client c + JOIN account.user u ON u.id = c.id + LEFT JOIN worker w ON w.id = c.salesPersonFk + LEFT JOIN account.user wu ON wu.id = w.userFk + WHERE c.id = ?`, [clientId]); } }, components: { @@ -37,7 +37,7 @@ module.exports = { 'attachment': attachment.build() }, props: { - clientId: { + recipientId: { required: true } } diff --git a/print/templates/email/sepa-core/sepa-core.html b/print/templates/email/sepa-core/sepa-core.html index b71c8e10ff..853597bf84 100644 --- a/print/templates/email/sepa-core/sepa-core.html +++ b/print/templates/email/sepa-core/sepa-core.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/email/sepa-core/sepa-core.js b/print/templates/email/sepa-core/sepa-core.js index 31afb11159..76f8d842f1 100755 --- a/print/templates/email/sepa-core/sepa-core.js +++ b/print/templates/email/sepa-core/sepa-core.js @@ -15,7 +15,7 @@ module.exports = { 'attachment': attachment.build() }, props: { - clientId: { + recipientId: { required: true }, companyId: { diff --git a/print/templates/reports/campaign-metrics/campaign-metrics.html b/print/templates/reports/campaign-metrics/campaign-metrics.html index ee1908164c..d125ab7e20 100644 --- a/print/templates/reports/campaign-metrics/campaign-metrics.html +++ b/print/templates/reports/campaign-metrics/campaign-metrics.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/reports/campaign-metrics/campaign-metrics.js b/print/templates/reports/campaign-metrics/campaign-metrics.js index f720692607..ef1d735dea 100755 --- a/print/templates/reports/campaign-metrics/campaign-metrics.js +++ b/print/templates/reports/campaign-metrics/campaign-metrics.js @@ -9,9 +9,8 @@ module.exports = { this.to = new Date(this.to); this.from = new Date(this.from); - this.client = await this.fetchClient(this.clientId); - - this.sales = await this.fetchSales(this.clientId, this.from, this.to); + this.client = await this.fetchClient(this.recipientId); + this.sales = await this.fetchSales(this.recipientId, this.from, this.to); if (!this.client) throw new Error('Something went wrong'); @@ -63,7 +62,7 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - clientId: { + recipientId: { required: true }, from: { diff --git a/print/templates/reports/claim-pickup-order/claim-pickup-order.html b/print/templates/reports/claim-pickup-order/claim-pickup-order.html index f23ee34014..59647cf9a3 100644 --- a/print/templates/reports/claim-pickup-order/claim-pickup-order.html +++ b/print/templates/reports/claim-pickup-order/claim-pickup-order.html @@ -1,5 +1,5 @@ - +
diff --git a/print/templates/reports/delivery-note/delivery-note.html b/print/templates/reports/delivery-note/delivery-note.html index 719397c085..9139461965 100644 --- a/print/templates/reports/delivery-note/delivery-note.html +++ b/print/templates/reports/delivery-note/delivery-note.html @@ -1,5 +1,5 @@ - +
@@ -88,10 +88,10 @@ - + - + - +
{{sale.itemFk}} {{sale.quantity}} {{sale.concept}}{{sale.price | currency('EUR', locale)}}{{sale.price | currency('EUR', $i18n.locale)}} {{(sale.discount / 100) | percentage}} {{sale.vatType}}{{sale.price * sale.quantity * (1 - sale.discount / 100) | currency('EUR', locale)}}{{sale.price * sale.quantity * (1 - sale.discount / 100) | currency('EUR', $i18n.locale)}}
@@ -125,7 +125,7 @@ {{$t('subtotal')}} {{getSubTotal() | currency('EUR', locale)}}{{getSubTotal() | currency('EUR', $i18n.locale)}}
@@ -149,13 +149,13 @@ {{service.description}} {{service.quantity}} {{service.taxDescription}} - {{service.price | currency('EUR', locale)}} + {{service.price | currency('EUR', $i18n.locale)}} - {{$t('total')}} {{serviceTotal | currency('EUR', locale)}} + {{$t('total')}} {{serviceTotal | currency('EUR', $i18n.locale)}} @@ -180,24 +180,24 @@ {{tax.name}} - {{tax.Base | currency('EUR', locale)}} + {{tax.Base | currency('EUR', $i18n.locale)}} {{tax.vatPercent | percentage}} - {{tax.tax | currency('EUR', locale)}} + {{tax.tax | currency('EUR', $i18n.locale)}} {{$t('subtotal')}} - {{getTotalBase() | currency('EUR', locale)}} + {{getTotalBase() | currency('EUR', $i18n.locale)}} - {{getTotalTax()| currency('EUR', locale)}} + {{getTotalTax()| currency('EUR', $i18n.locale)}} {{$t('total')}} - {{getTotal() | currency('EUR', locale)}} + {{getTotal() | currency('EUR', $i18n.locale)}} diff --git a/print/templates/reports/driver-route/driver-route.html b/print/templates/reports/driver-route/driver-route.html index ba9a339da0..919ed06792 100644 --- a/print/templates/reports/driver-route/driver-route.html +++ b/print/templates/reports/driver-route/driver-route.html @@ -1,5 +1,5 @@ - + @@ -141,7 +141,7 @@ - +
{{$t('import')}}{{ticket.import | currency('EUR', locale)}}{{ticket.import | currency('EUR', $i18n.locale)}}
diff --git a/print/templates/reports/entry-order/entry-order.html b/print/templates/reports/entry-order/entry-order.html index 5ee45787c9..3c1cdbd33a 100644 --- a/print/templates/reports/entry-order/entry-order.html +++ b/print/templates/reports/entry-order/entry-order.html @@ -1,5 +1,5 @@ - + @@ -77,8 +77,8 @@ - - + + - +
{{buy.packing}} {{buy.itemName}} {{buy.quantity | number}}{{buy.buyingValue | currency('EUR', locale)}}{{buy.buyingValue * buy.quantity | currency('EUR', locale)}}{{buy.buyingValue | currency('EUR', $i18n.locale)}}{{buy.buyingValue * buy.quantity | currency('EUR', $i18n.locale)}}
@@ -106,7 +106,7 @@ {{$t('total')}} {{getTotal() | currency('EUR', locale)}}{{getTotal() | currency('EUR', $i18n.locale)}}
diff --git a/print/templates/reports/item-label/item-label.html b/print/templates/reports/item-label/item-label.html index 0cb351b277..3f2d7ce690 100644 --- a/print/templates/reports/item-label/item-label.html +++ b/print/templates/reports/item-label/item-label.html @@ -1,5 +1,5 @@ - + diff --git a/print/templates/reports/letter-debtor/letter-debtor.html b/print/templates/reports/letter-debtor/letter-debtor.html index 534798f5e4..81a001765d 100644 --- a/print/templates/reports/letter-debtor/letter-debtor.html +++ b/print/templates/reports/letter-debtor/letter-debtor.html @@ -1,5 +1,5 @@ - +
diff --git a/print/templates/reports/letter-debtor/letter-debtor.js b/print/templates/reports/letter-debtor/letter-debtor.js index f099c18696..7da1b438c9 100755 --- a/print/templates/reports/letter-debtor/letter-debtor.js +++ b/print/templates/reports/letter-debtor/letter-debtor.js @@ -6,8 +6,8 @@ const reportFooter = new Component('report-footer'); module.exports = { name: 'letter-debtor', async serverPrefetch() { - this.client = await this.fetchClient(this.clientId); - this.sales = await this.fetchSales(this.clientId, this.companyId); + this.client = await this.fetchClient(this.recipientId); + this.sales = await this.fetchSales(this.recipientId, this.companyId); if (!this.client) throw new Error('Something went wrong'); @@ -79,7 +79,7 @@ module.exports = { 'report-footer': reportFooter.build() }, props: { - clientId: { + recipientId: { required: true }, companyId: { diff --git a/print/templates/reports/receipt/receipt.html b/print/templates/reports/receipt/receipt.html index 5538b7c3fa..9a4e1964c4 100644 --- a/print/templates/reports/receipt/receipt.html +++ b/print/templates/reports/receipt/receipt.html @@ -1,5 +1,5 @@ - +
diff --git a/print/templates/reports/sepa-core/sepa-core.html b/print/templates/reports/sepa-core/sepa-core.html index 720f70058d..d14a3ce6e8 100644 --- a/print/templates/reports/sepa-core/sepa-core.html +++ b/print/templates/reports/sepa-core/sepa-core.html @@ -1,5 +1,5 @@ - +
diff --git a/print/templates/reports/sepa-core/sepa-core.js b/print/templates/reports/sepa-core/sepa-core.js index de3a2983d4..a63b5b704d 100755 --- a/print/templates/reports/sepa-core/sepa-core.js +++ b/print/templates/reports/sepa-core/sepa-core.js @@ -6,8 +6,8 @@ const reportFooter = new Component('report-footer'); const rptSepaCore = { name: 'sepa-core', async serverPrefetch() { - this.client = await this.fetchClient(this.clientId, this.companyId); - this.supplier = await this.fetchSupplier(this.clientId, this.companyId); + this.client = await this.fetchClient(this.recipientId, this.companyId); + this.supplier = await this.fetchSupplier(this.recipientId, this.companyId); if (!this.client) throw new Error('Something went wrong'); @@ -67,7 +67,7 @@ const rptSepaCore = { 'report-footer': reportFooter.build() }, props: { - clientId: { + recipientId: { required: true }, companyId: { @@ -76,5 +76,4 @@ const rptSepaCore = { } }; - module.exports = rptSepaCore; diff --git a/print/templates/reports/zone/zone.html b/print/templates/reports/zone/zone.html index 8e6406ad45..c1e8d1ec14 100644 --- a/print/templates/reports/zone/zone.html +++ b/print/templates/reports/zone/zone.html @@ -1,5 +1,5 @@ - +