diff --git a/front/core/components/watcher/watcher.js b/front/core/components/watcher/watcher.js index ddef745fd..04ccba45e 100644 --- a/front/core/components/watcher/watcher.js +++ b/front/core/components/watcher/watcher.js @@ -100,7 +100,9 @@ export default class Watcher extends Component { */ submit() { try { - this.check(); + if (this.requestMethod() !== 'post') + this.check(); + else this.isInvalid(); } catch (err) { return this.$q.reject(err); } @@ -120,12 +122,12 @@ export default class Watcher extends Component { if (this.form) this.form.$setSubmitted(); - if (!this.dataChanged()) { + const isPost = (this.requestMethod() === 'post'); + if (!this.dataChanged() && !isPost) { this.updateOriginalData(); return this.$q.resolve(); } - let isPost = (this.$attrs.save && this.$attrs.save.toLowerCase() === 'post'); let changedData = isPost ? this.data : getModifiedData(this.data, this.orgData); @@ -158,7 +160,6 @@ export default class Watcher extends Component { }); } - return this.$q((resolve, reject) => { this.$http.post(this.url, changedData).then( json => this.writeData(json, resolve), @@ -167,6 +168,10 @@ export default class Watcher extends Component { }); } + requestMethod() { + return this.$attrs.save && this.$attrs.save.toLowerCase(); + } + /** * Checks if data is ready to send. */ @@ -177,6 +182,15 @@ export default class Watcher extends Component { throw new UserError('No changes to save'); } + /** + * Checks if data is ready to send. + */ + isInvalid() { + console.log(this.form.$invalid); + if (this.form && this.form.$invalid) + throw new UserError('Some fields are invalid'); + } + /** * Notifies the user that the data has been saved. */ diff --git a/loopback/locale/es.json b/loopback/locale/es.json index fe95bc065..e97518504 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -128,5 +128,6 @@ "Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}", "ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto", "Distance must be lesser than 1000": "La distancia debe ser inferior a 1000", - "This ticket is deleted": "Este ticket está eliminado" + "This ticket is deleted": "Este ticket está eliminado", + "The introduced data already exists": "La información introducida ya existe" } \ No newline at end of file diff --git a/modules/travel/back/models/travel.js b/modules/travel/back/models/travel.js index 4643f79fd..a7c045b31 100644 --- a/modules/travel/back/models/travel.js +++ b/modules/travel/back/models/travel.js @@ -1,3 +1,5 @@ +const UserError = require('vn-loopback/util/user-error'); + module.exports = Self => { require('../methods/travel/getTravel')(Self); require('../methods/travel/getEntries')(Self); @@ -5,4 +7,10 @@ module.exports = Self => { require('../methods/travel/createThermograph')(Self); require('../methods/travel/deleteThermograph')(Self); require('../methods/travel/updateThermograph')(Self); + + Self.rewriteDbError(function(err) { + if (err.code === 'ER_DUP_ENTRY') + return new UserError('The introduced data already exists'); + return err; + }); }; diff --git a/modules/travel/front/create/index.js b/modules/travel/front/create/index.js index 02be34ca7..513e1e0b1 100644 --- a/modules/travel/front/create/index.js +++ b/modules/travel/front/create/index.js @@ -2,6 +2,26 @@ import ngModule from '../module'; import Section from 'salix/components/section'; class Controller extends Section { + constructor($element, $, $stateParams) { + super($element, $); + this.$stateParams = $stateParams; + this.travel = {}; + } + + $onChanges() { + if (this.$stateParams && this.$stateParams.q) + this._travel = JSON.parse(this.$stateParams.q); + } + + get travel() { + return this._travel; + } + + set travel(value) { + this._travel = value; + if (!value) return; + } + onSubmit() { return this.$.watcher.submit().then( res => this.$state.go('travel.card.summary', {id: res.data.id}) @@ -9,6 +29,8 @@ class Controller extends Section { } } +Controller.$inject = ['$element', '$scope', '$stateParams']; + ngModule.component('vnTravelCreate', { template: require('./index.html'), controller: Controller diff --git a/modules/travel/front/create/index.spec.js b/modules/travel/front/create/index.spec.js index 63f0eda42..ef83d98ff 100644 --- a/modules/travel/front/create/index.spec.js +++ b/modules/travel/front/create/index.spec.js @@ -26,5 +26,22 @@ describe('Travel Component vnTravelCreate', () => { expect(controller.$state.go).toHaveBeenCalledWith('travel.card.summary', {id: 1234}); }); }); + + describe('$onChanges()', () => { + it('should update the travel data when stateParams.q is defined', () => { + controller.$stateParams = {q: { + ref: 1, + agencyModeFk: 1 + }}; + + const result = {q: { + ref: 1, + agencyModeFk: 1 + }}; + controller.$onChanges(); + + expect(controller._travel).toBe(result); + }); + }); }); diff --git a/modules/travel/front/index/index.html b/modules/travel/front/index/index.html index 3af99eb6b..ee7f88507 100644 --- a/modules/travel/front/index/index.html +++ b/modules/travel/front/index/index.html @@ -41,12 +41,19 @@ {{::travel.warehouseInName}} {{::travel.landed | date:'dd/MM/yyyy'}} - - - + + + + + + + @@ -65,4 +72,10 @@ fixed-bottom-right> + + \ No newline at end of file diff --git a/modules/travel/front/index/index.js b/modules/travel/front/index/index.js index a1e22d2e7..8402d00a2 100644 --- a/modules/travel/front/index/index.js +++ b/modules/travel/front/index/index.js @@ -1,16 +1,10 @@ import ngModule from '../module'; export default class Controller { - constructor($scope) { + constructor($scope, $state) { this.$ = $scope; this.ticketSelected = null; - } - - preview(event, travel) { - this.travelSelected = travel; - this.$.summary.show(); - event.preventDefault(); - event.stopImmediatePropagation(); + this.$state = $state; } getScopeDates(days) { @@ -35,9 +29,45 @@ export default class Controller { } else this.$.model.clear(); } + + stopEvent(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + + cloneTravel(event, travel) { + this.stopEvent(event); + this.travelSelected = travel; + this.$.clone.show(); + } + + onCloneAccept(response) { + if (!(response == 'accept' && this.travelSelected)) + return; + if (this.travelSelected) { + console.log('this.travelSelected', this.travelSelected); + const travel = { + ref: this.travelSelected.ref, + agencyModeFk: this.travelSelected.agencyFk, + shipped: this.travelSelected.shipped, + landed: this.travelSelected.landed, + warehouseInFk: this.travelSelected.warehouseInFk, + warehouseOutFk: this.travelSelected.warehouseOutFk + }; + const queryParams = JSON.stringify(travel); + this.$state.go('travel.create', {q: queryParams}); + } + + this.travelSelected = null; + } + preview(event, travel) { + this.stopEvent(event); + this.travelSelected = travel; + this.$.summary.show(); + } } -Controller.$inject = ['$scope']; +Controller.$inject = ['$scope', '$state']; ngModule.component('vnTravelIndex', { template: require('./index.html'), diff --git a/modules/travel/front/index/index.spec.js b/modules/travel/front/index/index.spec.js index 5affc7c1a..8e180e168 100644 --- a/modules/travel/front/index/index.spec.js +++ b/modules/travel/front/index/index.spec.js @@ -61,4 +61,48 @@ describe('Travel Component vnTravelIndex', () => { expect(range - dayInMilliseconds).toEqual(dayInMilliseconds + millisecondsPerAddedDay); }); }); + + describe('onCloneAccept()', () => { + it('should do nothing if response is not accept', () => { + jest.spyOn(controller.$state, 'go'); + + let response = 'ERROR!'; + controller.travelSelected = 'check me'; + + controller.onCloneAccept(response); + + expect(controller.$state.go).not.toHaveBeenCalledWith(); + expect(controller.travelSelected).toEqual('check me'); + }); + + it('should do nothing if response is accept but travelSelected is not defined in the controller', () => { + jest.spyOn(controller.$state, 'go'); + + let response = 'accept'; + controller.travelSelected = undefined; + + controller.onCloneAccept(response); + + expect(controller.$state.go).not.toHaveBeenCalledWith(); + expect(controller.travelSelected).toBeUndefined(); + }); + + it('should call go() then update travelSelected in the controller', () => { + jest.spyOn(controller.$state, 'go'); + + let response = 'accept'; + controller.travelSelected = { + ref: 1, + agencyFk: 1}; + const travel = { + ref: controller.travelSelected.ref, + agencyModeFk: controller.travelSelected.agencyFk + }; + const queryParams = JSON.stringify(travel); + controller.onCloneAccept(response); + + expect(controller.$state.go).toHaveBeenCalledWith('travel.create', {q: queryParams}); + expect(controller.travelSelected).toBeNull(); + }); + }); }); diff --git a/modules/travel/front/index/locale/es.yml b/modules/travel/front/index/locale/es.yml new file mode 100644 index 000000000..63d23affd --- /dev/null +++ b/modules/travel/front/index/locale/es.yml @@ -0,0 +1,2 @@ +Do you want to clone this travel?: ¿Desea clonar este envio? +All it's properties will be copied: Todas sus propiedades serán copiadas \ No newline at end of file diff --git a/modules/travel/front/routes.json b/modules/travel/front/routes.json index 50e236889..b802aaa4a 100644 --- a/modules/travel/front/routes.json +++ b/modules/travel/front/routes.json @@ -54,7 +54,7 @@ "component": "vn-travel-log", "description": "Log" }, { - "url": "/create", + "url": "/create?q", "state": "travel.create", "component": "vn-travel-create", "description": "New travel"