diff --git a/db/changes/10281-valentineDay/00-ACL.sql b/db/changes/10281-valentineDay/00-ACL.sql new file mode 100644 index 0000000000..41626d4d6f --- /dev/null +++ b/db/changes/10281-valentineDay/00-ACL.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('Entry', '*', '*', 'ALLOW', 'ROLE', 'administrative'); diff --git a/e2e/paths/02-client/14_balance.spec.js b/e2e/paths/02-client/14_balance.spec.js index 22d3f15ac0..d408215ff3 100644 --- a/e2e/paths/02-client/14_balance.spec.js +++ b/e2e/paths/02-client/14_balance.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors'; import getBrowser from '../../helpers/puppeteer'; -fdescribe('Client balance path', () => { +describe('Client balance path', () => { let browser; let page; beforeAll(async() => { @@ -47,6 +47,7 @@ fdescribe('Client balance path', () => { await page.closePopup(); await page.waitToClick(selectors.clientBalance.newPaymentButton); await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Cash'); + await page.clearInput(selectors.clientBalance.newDescription); await page.write(selectors.clientBalance.newDescription, 'Description'); await page.waitToClick(selectors.clientBalance.saveButton); const message = await page.waitForSnackbar(); @@ -86,7 +87,8 @@ fdescribe('Client balance path', () => { await page.waitToClick(selectors.clientBalance.newPaymentButton); await page.write(selectors.clientBalance.newPaymentAmount, amountPaid); - + await page.clearInput(selectors.clientBalance.newDescription); + await page.write(selectors.clientBalance.newDescription, 'Payment'); await page.write(selectors.clientBalance.deliveredAmount, cashHanded); const refund = await page.waitToGetProperty(selectors.clientBalance.refundAmount, 'value'); await page.waitToClick(selectors.clientBalance.saveButton); @@ -107,6 +109,7 @@ fdescribe('Client balance path', () => { await page.waitToClick(selectors.clientBalance.newPaymentButton); await page.autocompleteSearch(selectors.clientBalance.newPaymentBank, 'Pay on receipt'); await page.overwrite(selectors.clientBalance.newPaymentAmount, '-150'); + await page.clearInput(selectors.clientBalance.newDescription); await page.write(selectors.clientBalance.newDescription, 'Description'); await page.waitToClick(selectors.clientBalance.saveButton); const message = await page.waitForSnackbar(); diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 1b5fbd917c..174a9e0938 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -167,10 +167,12 @@ "You can't upload images on the test environment": "No puedes subir imágenes en el entorno de pruebas", "The selected ticket is not suitable for this route": "El ticket seleccionado no es apto para esta ruta", "Sorts whole route": "Reordena ruta entera", - "Invalid account": "Cuenta inválida", - "New ticket request has been created with price": "Se ha creado una nueva petición de compra *'{{description}}'* para el día *{{shipped}}*, con una cantidad de *{{quantity}}* y un precio de *{{price}} €*", - "New ticket request has been created": "Se ha creado una nueva petición de compra *'{{description}}'* para el día *{{shipped}}*, con una cantidad de *{{quantity}}*", + "New ticket request has been created with price": "Se ha creado una nueva petición de compra '{{description}}' para el día {{shipped}}, con una cantidad de {{quantity}} y un precio de {{price}} €", + "New ticket request has been created": "Se ha creado una nueva petición de compra '{{description}}' para el día {{shipped}}, con una cantidad de {{quantity}}", + "Swift / BIC cannot be empty": "Swift / BIC no puede estar vacío", + "This BIC already exist.": "Este BIC ya existe.", "That item doesn't exists": "Ese artículo no existe", "There's a new urgent ticket": "Hay un nuevo ticket urgente: [{{title}}](https://cau.verdnatura.es/WorkOrder.do?woMode=viewWO&woID={{issueId}})", + "Invalid account": "Cuenta inválida", "Compensation account is empty": "La cuenta para compensar está vacia" } \ No newline at end of file diff --git a/modules/client/back/models/bank-entity.js b/modules/client/back/models/bank-entity.js index 4cfa7fc918..565c27752c 100644 --- a/modules/client/back/models/bank-entity.js +++ b/modules/client/back/models/bank-entity.js @@ -1,8 +1,11 @@ module.exports = Self => { Self.validatesPresenceOf('name', { - message: `Name cannot be blank` + message: 'Name cannot be blank' }); Self.validatesPresenceOf('bic', { - message: `Swift / BIC can't be empty` + message: 'Swift / BIC cannot be empty' + }); + Self.validatesUniquenessOf('bic', { + message: 'This BIC already exist.' }); }; diff --git a/modules/entry/front/routes.json b/modules/entry/front/routes.json index db12e95fd9..1911f721cf 100644 --- a/modules/entry/front/routes.json +++ b/modules/entry/front/routes.json @@ -31,19 +31,19 @@ "state": "entry.index", "component": "vn-entry-index", "description": "Entries", - "acl": ["buyer"] + "acl": ["buyer", "administrative"] }, { "url": "/latest-buys?q", "state": "entry.latestBuys", "component": "vn-entry-latest-buys", "description": "Latest buys", - "acl": ["buyer"] + "acl": ["buyer", "administrative"] }, { "url": "/create?supplierFk&travelFk&companyFk", "state": "entry.create", "component": "vn-entry-create", "description": "New entry", - "acl": ["buyer"] + "acl": ["buyer", "administrative"] }, { "url": "/:id", "state": "entry.card", diff --git a/modules/travel/back/methods/travel/getAverageDays.js b/modules/travel/back/methods/travel/getAverageDays.js new file mode 100644 index 0000000000..bcc98dbe2f --- /dev/null +++ b/modules/travel/back/methods/travel/getAverageDays.js @@ -0,0 +1,32 @@ +module.exports = Self => { + Self.remoteMethod('getAverageDays', { + description: 'Returns the average days duration and the two warehouses of the travel.', + accessType: 'READ', + accepts: [{ + arg: 'agencyModeFk', + type: 'number', + required: true + }], + returns: { + type: 'number', + root: true + }, + http: { + path: `/getAverageDays`, + verb: 'GET' + } + }); + + Self.getAverageDays = async agencyModeFk => { + const query = ` + SELECT t.id, t.warehouseInFk, t.warehouseOutFk, + (SELECT ROUND(AVG(DATEDIFF(t.landed, t.shipped ))) + FROM travel t + WHERE t.agencyFk = ? LIMIT 50) AS dayDuration + FROM travel t + WHERE t.agencyFk = ? ORDER BY t.id DESC LIMIT 1;`; + + const [avgDays] = await Self.rawSql(query, [agencyModeFk, agencyModeFk]); + return avgDays; + }; +}; diff --git a/modules/travel/back/models/travel.js b/modules/travel/back/models/travel.js index 46d33b305d..046153ee22 100644 --- a/modules/travel/back/models/travel.js +++ b/modules/travel/back/models/travel.js @@ -8,6 +8,7 @@ module.exports = Self => { require('../methods/travel/deleteThermograph')(Self); require('../methods/travel/updateThermograph')(Self); require('../methods/travel/extraCommunityFilter')(Self); + require('../methods/travel/getAverageDays')(Self); require('../methods/travel/cloneWithEntries')(Self); Self.rewriteDbError(function(err) { diff --git a/modules/travel/front/create/index.html b/modules/travel/front/create/index.html index 0931c322ee..6c19e0e124 100644 --- a/modules/travel/front/create/index.html +++ b/modules/travel/front/create/index.html @@ -20,6 +20,7 @@ diff --git a/modules/travel/front/create/index.js b/modules/travel/front/create/index.js index 9a9c5ce9db..cf0b2f3827 100644 --- a/modules/travel/front/create/index.js +++ b/modules/travel/front/create/index.js @@ -7,6 +7,31 @@ class Controller extends Section { this.travel = JSON.parse(this.$params.q); } + onShippedChange(value) { + let hasFilledProperties; + let hasAgencyMode; + if (this.travel) { + hasAgencyMode = Boolean(this.travel.agencyModeFk); + hasFilledProperties = this.travel.landed || this.travel.warehouseInFk || this.travel.warehouseOutFk; + } + if (!hasAgencyMode || hasFilledProperties) + return; + + const query = `travels/getAverageDays`; + const params = { + agencyModeFk: this.travel.agencyModeFk + }; + this.$http.get(query, {params}).then(res => { + const landed = new Date(value); + const futureDate = landed.getDate() + res.data.dayDuration; + landed.setDate(futureDate); + + this.travel.landed = landed; + this.travel.warehouseInFk = res.data.warehouseInFk; + this.travel.warehouseOutFk = res.data.warehouseOutFk; + }); + } + onSubmit() { return this.$.watcher.submit().then( res => this.$state.go('travel.card.basicData', {id: res.data.id}) diff --git a/modules/travel/front/create/index.spec.js b/modules/travel/front/create/index.spec.js index 99f52b322c..b59530604c 100644 --- a/modules/travel/front/create/index.spec.js +++ b/modules/travel/front/create/index.spec.js @@ -5,10 +5,12 @@ describe('Travel Component vnTravelCreate', () => { let $scope; let $state; let controller; + let $httpBackend; beforeEach(ngModule('travel')); - beforeEach(inject(($componentController, $rootScope, _$state_) => { + beforeEach(inject(($componentController, $rootScope, _$state_, _$httpBackend_) => { + $httpBackend = _$httpBackend_; $scope = $rootScope.$new(); $state = _$state_; $scope.watcher = watcher; @@ -38,4 +40,34 @@ describe('Travel Component vnTravelCreate', () => { expect(controller.travel).toEqual(json); }); }); + + describe('onShippedChange()', () => { + it(`should do nothing if there's no agencyModeFk in the travel.`, () => { + controller.travel = {}; + controller.onShippedChange(); + + expect(controller.travel.landed).toBeUndefined(); + expect(controller.travel.warehouseInFk).toBeUndefined(); + expect(controller.travel.warehouseOutFk).toBeUndefined(); + }); + + it(`should fill the fields when it's selected a date and agency.`, () => { + controller.travel = {agencyModeFk: 1}; + const tomorrow = new Date(); + tomorrow.setDate(tomorrow.getDate() + 1); + const expectedResponse = { + dayDuration: 2, + warehouseInFk: 1, + warehouseOutFk: 2 + }; + + const query = `travels/getAverageDays?agencyModeFk=${controller.travel.agencyModeFk}`; + $httpBackend.expectGET(query).respond(expectedResponse); + controller.onShippedChange(tomorrow); + $httpBackend.flush(); + + expect(controller.travel.warehouseInFk).toEqual(expectedResponse.warehouseInFk); + expect(controller.travel.warehouseOutFk).toEqual(expectedResponse.warehouseOutFk); + }); + }); });