diff --git a/db/changes/10190-PostErte/00-ACL.sql b/db/changes/10190-PostErte/00-ACL.sql new file mode 100644 index 000000000..d19901d48 --- /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 ecf0d37e3..2f36dc584 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 67a62381a..e7f1e234d 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 000000000..0bc8f8eb6 --- /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 000000000..b49a952e4 --- /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 d65ca71df..f56183df2 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 eeb18fb73..d77b6d290 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/order/back/methods/order/getSourceValues.js b/modules/order/back/methods/order/getSourceValues.js index da3685c62..5e9f0e6dc 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/travel/back/methods/thermograph/createThermograph.js b/modules/travel/back/methods/thermograph/createThermograph.js new file mode 100644 index 000000000..bfca208fe --- /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 000000000..188c3a530 --- /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 000000000..733b713f0 --- /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 000000000..1d510b513 --- /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 000000000..3f95a0670 --- /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 421ae4341..2519fffc4 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 0d70edd7e..a16e68b98 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 b8f7fa41a..70ee0de07 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 4b1fc8cf4..0232c1b12 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 6c0464991..d398febf1 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 58fbe3991..23976fc96 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 9f9be564b..0e3bc99fc 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