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);
+ });
+ });
});