diff --git a/db/changes/10340-summer/00-ACL.sql b/db/changes/10340-summer/00-ACL.sql
new file mode 100644
index 000000000..a9a5778e5
--- /dev/null
+++ b/db/changes/10340-summer/00-ACL.sql
@@ -0,0 +1,4 @@
+DELETE FROM `salix`.`ACL` WHERE id = 189;
+DELETE FROM `salix`.`ACL` WHERE id = 188;
+UPDATE `salix`.`ACL` tdms SET tdms.accessType = '*'
+ WHERE tdms.id = 165;
diff --git a/db/changes/10340-summer/deleteMe.keep b/db/changes/10340-summer/deleteMe.keep
deleted file mode 100644
index 3a94d75a8..000000000
--- a/db/changes/10340-summer/deleteMe.keep
+++ /dev/null
@@ -1 +0,0 @@
-Delete me
\ No newline at end of file
diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js
index ffb45c34e..4c7c18689 100644
--- a/e2e/helpers/selectors.js
+++ b/e2e/helpers/selectors.js
@@ -646,6 +646,12 @@ export default {
saveServiceButton: 'button[type=submit]',
saveServiceTypeButton: '.vn-dialog.shown tpl-buttons > button'
},
+ ticketDms: {
+ import: 'vn-ticket-dms-index vn-button[icon="file_copy"]',
+ document: 'vn-autocomplete[ng-model="$ctrl.dmsId"]',
+ saveImport: 'button[response="accept"]',
+ anyDocument: 'vn-ticket-dms-index > vn-data-viewer vn-tbody vn-tr'
+ },
createStateView: {
state: 'vn-autocomplete[ng-model="$ctrl.stateFk"]',
worker: 'vn-autocomplete[ng-model="$ctrl.workerFk"]',
diff --git a/e2e/paths/05-ticket/19_dms.spec.js b/e2e/paths/05-ticket/19_dms.spec.js
new file mode 100644
index 000000000..be2ac4338
--- /dev/null
+++ b/e2e/paths/05-ticket/19_dms.spec.js
@@ -0,0 +1,49 @@
+import selectors from '../../helpers/selectors.js';
+import getBrowser from '../../helpers/puppeteer';
+
+describe('Ticket DMS path', () => {
+ let browser;
+ let page;
+
+ beforeAll(async() => {
+ browser = await getBrowser();
+ page = browser.page;
+ await page.loginAndModule('employee', 'ticket');
+ await page.accessToSearchResult('1');
+ await page.accessToSection('ticket.card.dms.index');
+ });
+
+ afterAll(async() => {
+ await browser.close();
+ });
+
+ it('should import a document', async() => {
+ await page.waitToClick(selectors.ticketDms.import);
+ await page.autocompleteSearch(selectors.ticketDms.document, '1');
+ await page.waitToClick(selectors.ticketDms.saveImport);
+ const message = await page.waitForSnackbar();
+
+ expect(message.text).toContain('Data saved!');
+ });
+
+ it(`should check there's a listed document now`, async() => {
+ const result = await page.countElement(selectors.ticketDms.anyDocument);
+
+ expect(result).toEqual(1);
+ });
+
+ it('should attempt to import an existing document on this ticket', async() => {
+ await page.waitToClick(selectors.ticketDms.import);
+ await page.autocompleteSearch(selectors.ticketDms.document, '1');
+ await page.waitToClick(selectors.ticketDms.saveImport);
+ const message = await page.waitForSnackbar();
+
+ expect(message.text).toContain('This document already exists on this ticket');
+ });
+
+ it(`should check there's still one document`, async() => {
+ const result = await page.countElement(selectors.ticketDms.anyDocument);
+
+ expect(result).toEqual(1);
+ });
+});
diff --git a/loopback/locale/en.json b/loopback/locale/en.json
index 9bef13527..75804ba21 100644
--- a/loopback/locale/en.json
+++ b/loopback/locale/en.json
@@ -98,5 +98,6 @@
"Client assignment has changed": "I did change the salesperson ~*\"<{{previousWorkerName}}>\"*~ by *\"<{{currentWorkerName}}>\"* from the client [{{clientName}} ({{clientId}})]({{{url}}})",
"None": "None",
"error densidad = 0": "error densidad = 0",
- "nickname": "nickname"
+ "nickname": "nickname",
+ "This document already exists on this ticket": "This document already exists on this ticket"
}
\ No newline at end of file
diff --git a/loopback/locale/es.json b/loopback/locale/es.json
index e2194b8ad..872d45ae0 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -181,5 +181,6 @@
"This specie already exist": "Esta especie ya existe",
"Client assignment has changed": "He cambiado el comercial ~*\"<{{previousWorkerName}}>\"*~ por *\"<{{currentWorkerName}}>\"* del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
"None": "Ninguno",
- "The contract was not active during the selected date": "El contrato no estaba activo durante la fecha seleccionada"
+ "The contract was not active during the selected date": "El contrato no estaba activo durante la fecha seleccionada",
+ "This document already exists on this ticket": "Este documento ya existe en el ticket"
}
\ No newline at end of file
diff --git a/modules/monitor/front/index/tickets/index.html b/modules/monitor/front/index/tickets/index.html
index 6f985d0a6..f61c62f16 100644
--- a/modules/monitor/front/index/tickets/index.html
+++ b/modules/monitor/front/index/tickets/index.html
@@ -33,14 +33,14 @@
-
+
Client
Salesperson
Date
Hour
Closure
Province
- State
+ State
Zone
Total
@@ -50,7 +50,7 @@
-
+
-
+
{{::ticket.shipped | date: 'HH:mm'}}
{{::ticket.zoneLanding | date: 'HH:mm'}}
{{::ticket.province}}
-
+
vn-icon {
diff --git a/modules/route/back/methods/route/summary.js b/modules/route/back/methods/route/summary.js
index ad65edb4a..10cfe38ee 100644
--- a/modules/route/back/methods/route/summary.js
+++ b/modules/route/back/methods/route/summary.js
@@ -48,12 +48,12 @@ module.exports = Self => {
scope: {
fields: ['id', 'm3', 'numberPlate']
}
- }
- ],
+ },
+ ]
};
summary.route = await Self.app.models.Route.findOne(filter);
- summary.tickets = await Self.app.models.Route.getTickets({id: id});
+ summary.tickets = await Self.app.models.Route.getTickets({id: id, order: 'priority ASC'});
return summary;
};
diff --git a/modules/route/front/index/index.spec.js b/modules/route/front/index/index.spec.js
index 8143f1157..80e660b76 100644
--- a/modules/route/front/index/index.spec.js
+++ b/modules/route/front/index/index.spec.js
@@ -133,7 +133,7 @@ describe('Component vnRouteIndex', () => {
});
describe('insert()', () => {
- it('should make a HTTP patch query and then call both refresh and showSuccess methods', () => {
+ it('should perform a HTTP patch query and then call both refresh and showSuccess methods', () => {
jest.spyOn(controller.$.model, 'refresh').mockReturnThis();
jest.spyOn(controller.vnApp, 'showSuccess');
diff --git a/modules/route/front/tickets/index.js b/modules/route/front/tickets/index.js
index ffae4bac5..efb3d1498 100644
--- a/modules/route/front/tickets/index.js
+++ b/modules/route/front/tickets/index.js
@@ -131,6 +131,7 @@ class Controller extends Section {
.then(() => {
this.$.model.data = this.$.model.data.concat(tickets);
this.vnApp.showSuccess(this.$t('Data saved!'));
+ this.updateVolume();
});
}
@@ -157,8 +158,7 @@ class Controller extends Section {
const query = `Routes/${this.route.id}/insertTicket`;
return this.$http.patch(query, {ticketId}).then(() => {
this.vnApp.showSuccess(this.$t('Data saved!'));
- this.$.model.refresh();
- this.card.reload();
+ this.updateVolume();
}).catch(error => {
if (error.status == 404)
return this.vnApp.showError(this.$t('Ticket not found'));
diff --git a/modules/route/front/tickets/index.spec.js b/modules/route/front/tickets/index.spec.js
index 1fcf92448..4fafc4750 100644
--- a/modules/route/front/tickets/index.spec.js
+++ b/modules/route/front/tickets/index.spec.js
@@ -129,19 +129,20 @@ describe('Route', () => {
describe('removeTicketFromRoute()', () => {
it('should perform a patch query then call showSuccess and updateVolume methods', () => {
- jest.spyOn(controller, 'updateVolume').mockReturnThis();
+ controller.$params = {id: 1101};
+
jest.spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$.model, 'remove');
let ticketId = 1;
controller.selectedTicket = ticketId;
+ $httpBackend.whenPOST(`Routes/${controller.$params.id}/updateVolume`).respond(200);
$httpBackend.expectPATCH(`Tickets/${ticketId}/`).respond('ok');
controller.removeTicketFromRoute();
$httpBackend.flush();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Ticket removed from route');
- expect(controller.updateVolume).toHaveBeenCalledWith();
});
});
@@ -196,9 +197,8 @@ describe('Route', () => {
describe('setTicketsRoute()', () => {
it('should perform a POST query to add tickets to the route', () => {
- controller.$.model = {data: [
- {id: 1, checked: false}
- ]};
+ controller.$params = {id: 1101};
+ controller.$.model.data = [{id: 1, checked: false}];
const existingTicket = controller.$.model.data[0];
@@ -217,7 +217,8 @@ describe('Route', () => {
{id: 5}
];
- $httpBackend.expectPOST(`Tickets/crud`).respond();
+ $httpBackend.whenPOST(`Routes/${controller.$params.id}/updateVolume`).respond(200);
+ $httpBackend.expectPOST('Tickets/crud').respond();
controller.setTicketsRoute();
$httpBackend.flush();
@@ -273,11 +274,15 @@ describe('Route', () => {
describe('insert()', () => {
it('should make a HTTP patch query and then call both refresh and showSuccess methods', () => {
+ controller.$params = {id: 1101};
+
jest.spyOn(controller.$.model, 'refresh').mockReturnThis();
jest.spyOn(controller.vnApp, 'showSuccess');
const ticketId = 11;
const data = {ticketId};
+
+ $httpBackend.whenPOST(`Routes/${controller.$params.id}/updateVolume`).respond(200);
$httpBackend.expect('PATCH', `Routes/1/insertTicket`, data).respond();
controller.insert(ticketId);
$httpBackend.flush();
diff --git a/modules/ticket/back/methods/ticket/isEditable.js b/modules/ticket/back/methods/ticket/isEditable.js
index 1cdca9f11..a444691ac 100644
--- a/modules/ticket/back/methods/ticket/isEditable.js
+++ b/modules/ticket/back/methods/ticket/isEditable.js
@@ -32,7 +32,9 @@ module.exports = Self => {
const isSalesAssistant = await Self.app.models.Account.hasRole(userId, 'salesAssistant', myOptions);
const isProductionBoss = await Self.app.models.Account.hasRole(userId, 'productionBoss', myOptions);
- const isValidRole = isSalesAssistant || isProductionBoss;
+ const isBuyer = await Self.app.models.Account.hasRole(userId, 'buyer', myOptions);
+
+ const isValidRole = isSalesAssistant || isProductionBoss || isBuyer;
let alertLevel = state ? state.alertLevel : null;
let ticket = await Self.app.models.Ticket.findById(id, {
diff --git a/modules/ticket/back/models/ticket-dms.js b/modules/ticket/back/models/ticket-dms.js
index ddb338632..9bceaae6e 100644
--- a/modules/ticket/back/models/ticket-dms.js
+++ b/modules/ticket/back/models/ticket-dms.js
@@ -1,3 +1,11 @@
+const UserError = require('vn-loopback/util/user-error');
+
module.exports = Self => {
require('../methods/ticket-dms/removeFile')(Self);
+
+ Self.rewriteDbError(function(err) {
+ if (err.code === 'ER_DUP_ENTRY')
+ return new UserError('This document already exists on this ticket');
+ return err;
+ });
};
diff --git a/modules/ticket/back/models/ticket-dms.json b/modules/ticket/back/models/ticket-dms.json
index b7b24dce0..8bcff254c 100644
--- a/modules/ticket/back/models/ticket-dms.json
+++ b/modules/ticket/back/models/ticket-dms.json
@@ -12,7 +12,7 @@
},
"properties": {
"dmsFk": {
- "type": "Number",
+ "type": "number",
"id": true,
"required": true
}
diff --git a/modules/ticket/front/dms/index/index.html b/modules/ticket/front/dms/index/index.html
index 203ceb635..526a3e379 100644
--- a/modules/ticket/front/dms/index/index.html
+++ b/modules/ticket/front/dms/index/index.html
@@ -96,18 +96,48 @@
+
-
-
-
-
+
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+ Save
+
+
\ No newline at end of file
diff --git a/modules/ticket/front/dms/index/index.js b/modules/ticket/front/dms/index/index.js
index da6aa6b6f..2ec7e03c0 100644
--- a/modules/ticket/front/dms/index/index.js
+++ b/modules/ticket/front/dms/index/index.js
@@ -55,6 +55,28 @@ class Controller extends Section {
downloadFile(dmsId) {
this.vnFile.download(`api/dms/${dmsId}/downloadFile`);
}
+
+ importDms() {
+ try {
+ if (!this.dmsId)
+ throw new Error(`The document indentifier can't be empty`);
+
+ const data = {
+ ticketFk: this.$params.id,
+ dmsFk: this.dmsId
+ };
+
+ this.$http.post('ticketDms', data).then(() => {
+ this.vnApp.showSuccess(this.$t('Data saved!'));
+ this.dmsId = null;
+ this.$.model.refresh();
+ });
+ } catch (e) {
+ this.vnApp.showError(this.$t(e.message));
+ return false;
+ }
+ return true;
+ }
}
Controller.$inject = ['$element', '$scope', 'vnFile'];
diff --git a/modules/ticket/front/dms/locale/es.yml b/modules/ticket/front/dms/locale/es.yml
index 998960a8e..fe31838f8 100644
--- a/modules/ticket/front/dms/locale/es.yml
+++ b/modules/ticket/front/dms/locale/es.yml
@@ -6,4 +6,7 @@ FileDescription: Ticket id {{ticketId}} del cliente {{clientName}} id {{clientId
Generate identifier for original file: Generar identificador para archivo original
ContentTypesInfo: 'Tipos de archivo permitidos: {{allowedContentTypes}}'
Are you sure you want to continue?: ¿Seguro que quieres continuar?
-File management: Gestión documental
\ No newline at end of file
+File management: Gestión documental
+Select document id: Introduzca id de gestion documental
+Import from existing: Importar desde existente
+The document indentifier can't be empty: El número de documento no puede estar vacío
\ No newline at end of file