diff --git a/db/changes/225001/.gitkeep b/db/changes/225001/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/db/changes/225001/00-entryDeleteRef.sql b/db/changes/225201/00-entryDeleteRef.sql
similarity index 100%
rename from db/changes/225001/00-entryDeleteRef.sql
rename to db/changes/225201/00-entryDeleteRef.sql
diff --git a/db/changes/225001/00-invoiceInConfig.sql b/db/changes/225201/00-invoiceInConfig.sql
similarity index 100%
rename from db/changes/225001/00-invoiceInConfig.sql
rename to db/changes/225201/00-invoiceInConfig.sql
diff --git a/db/changes/225001/00-supplier_beforeUpdate.sql b/db/changes/225201/00-supplier_beforeUpdate.sql
similarity index 100%
rename from db/changes/225001/00-supplier_beforeUpdate.sql
rename to db/changes/225201/00-supplier_beforeUpdate.sql
diff --git a/db/changes/225201/00-ticket_canbePostponed.sql b/db/changes/225201/00-ticket_canbePostponed.sql
new file mode 100644
index 000000000..572824b4b
--- /dev/null
+++ b/db/changes/225201/00-ticket_canbePostponed.sql
@@ -0,0 +1,73 @@
+DROP PROCEDURE IF EXISTS `vn`.`ticket_canbePostponed`;
+
+DELIMITER $$
+$$
+CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canbePostponed`(vOriginDated DATE, vFutureDated DATE, vWarehouseFk INT)
+BEGIN
+/**
+ * Devuelve un listado de tickets susceptibles de fusionarse con otros tickets en el futuro
+ *
+ * @param vOriginDated Fecha en cuestión
+ * @param vFutureDated Fecha en el futuro a sondear
+ * @param vWarehouseFk Identificador de vn.warehouse
+ */
+ DROP TEMPORARY TABLE IF EXISTS tmp.filter;
+ CREATE TEMPORARY TABLE tmp.filter
+ (INDEX (id))
+ SELECT sv.ticketFk id,
+ sub2.id futureId,
+ GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) ipt,
+ CAST(sum(litros) AS DECIMAL(10,0)) liters,
+ CAST(count(*) AS DECIMAL(10,0)) `lines`,
+ st.name state,
+ sub2.iptd futureIpt,
+ sub2.state futureState,
+ t.clientFk,
+ t.warehouseFk,
+ ts.alertLevel,
+ t.shipped,
+ sub2.shipped futureShipped,
+ t.workerFk,
+ st.code stateCode,
+ sub2.code futureStateCode
+ FROM vn.saleVolume sv
+ JOIN vn.sale s ON s.id = sv.saleFk
+ JOIN vn.item i ON i.id = s.itemFk
+ JOIN vn.ticket t ON t.id = sv.ticketFk
+ JOIN vn.address a ON a.id = t.addressFk
+ JOIN vn.province p ON p.id = a.provinceFk
+ JOIN vn.country c ON c.id = p.countryFk
+ JOIN vn.ticketState ts ON ts.ticketFk = t.id
+ JOIN vn.state st ON st.id = ts.stateFk
+ JOIN vn.alertLevel al ON al.id = ts.alertLevel
+ LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id
+ LEFT JOIN (
+ SELECT *
+ FROM (
+ SELECT
+ t.addressFk,
+ t.id,
+ t.shipped,
+ st.name state,
+ st.code code,
+ GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) iptd
+ FROM vn.ticket t
+ JOIN vn.ticketState ts ON ts.ticketFk = t.id
+ JOIN vn.state st ON st.id = ts.stateFk
+ JOIN vn.sale s ON s.ticketFk = t.id
+ JOIN vn.item i ON i.id = s.itemFk
+ WHERE t.shipped BETWEEN vFutureDated
+ AND util.dayend(vFutureDated)
+ AND t.warehouseFk = vWarehouseFk
+ GROUP BY t.id
+ ) sub
+ GROUP BY sub.addressFk
+ ) sub2 ON sub2.addressFk = t.addressFk AND t.id != sub2.id
+ WHERE t.shipped BETWEEN vOriginDated AND util.dayend(vOriginDated)
+ AND t.warehouseFk = vWarehouseFk
+ AND al.code = 'FREE'
+ AND tp.ticketFk IS NULL
+ GROUP BY sv.ticketFk
+ HAVING futureId;
+END$$
+DELIMITER ;
diff --git a/db/changes/225001/01-modules.sql b/db/changes/225201/01-modules.sql
similarity index 100%
rename from db/changes/225001/01-modules.sql
rename to db/changes/225201/01-modules.sql
diff --git a/db/changes/225001/02-starredModule.sql b/db/changes/225201/02-starredModule.sql
similarity index 100%
rename from db/changes/225001/02-starredModule.sql
rename to db/changes/225201/02-starredModule.sql
diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js
index f550e3a9d..dba94dd22 100644
--- a/e2e/helpers/selectors.js
+++ b/e2e/helpers/selectors.js
@@ -735,18 +735,16 @@ export default {
},
ticketFuture: {
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
- originDated: 'vn-date-picker[label="Origin ETD"]',
- futureDated: 'vn-date-picker[label="Destination ETD"]',
- shipped: 'vn-date-picker[label="Origin date"]',
- tfShipped: 'vn-date-picker[label="Destination date"]',
+ originDated: 'vn-date-picker[label="Origin date"]',
+ futureDated: 'vn-date-picker[label="Destination date"]',
linesMax: 'vn-textfield[label="Max Lines"]',
litersMax: 'vn-textfield[label="Max Liters"]',
ipt: 'vn-autocomplete[label="Origin IPT"]',
- tfIpt: 'vn-autocomplete[label="Destination IPT"]',
+ futureIpt: 'vn-autocomplete[label="Destination IPT"]',
tableIpt: 'vn-autocomplete[name="ipt"]',
- tableTfIpt: 'vn-autocomplete[name="tfIpt"]',
+ tableFutureIpt: 'vn-autocomplete[name="futureIpt"]',
state: 'vn-autocomplete[label="Origin Grouped State"]',
- tfState: 'vn-autocomplete[label="Destination Grouped State"]',
+ futureState: 'vn-autocomplete[label="Destination Grouped State"]',
warehouseFk: 'vn-autocomplete[label="Warehouse"]',
problems: 'vn-check[label="With problems"]',
tableButtonSearch: 'vn-button[vn-tooltip="Search"]',
@@ -755,9 +753,9 @@ export default {
firstCheck: 'tbody > tr:nth-child(1) > td > vn-check',
multiCheck: 'vn-multi-check',
tableId: 'vn-textfield[name="id"]',
- tableTfId: 'vn-textfield[name="ticketFuture"]',
- tableLiters: 'vn-textfield[name="litersMax"]',
- tableLines: 'vn-textfield[name="linesMax"]',
+ tableFutureId: 'vn-textfield[name="futureId"]',
+ tableLiters: 'vn-textfield[name="liters"]',
+ tableLines: 'vn-textfield[name="lines"]',
submit: 'vn-submit[label="Search"]',
table: 'tbody > tr:not(.empty-rows)'
},
diff --git a/e2e/paths/01-salix/04_recoverPassword.spec.js b/e2e/paths/01-salix/04_recoverPassword.spec.js
index 80ef32cb5..67e6362d3 100644
--- a/e2e/paths/01-salix/04_recoverPassword.spec.js
+++ b/e2e/paths/01-salix/04_recoverPassword.spec.js
@@ -1,7 +1,8 @@
import selectors from '../../helpers/selectors';
import getBrowser from '../../helpers/puppeteer';
-describe('Login path', async() => {
+// https://redmine.verdnatura.es/issues/4995 fix login
+xdescribe('RecoverPassword path', async() => {
let browser;
let page;
diff --git a/e2e/paths/05-ticket/20_future.spec.js b/e2e/paths/05-ticket/21_future.spec.js
similarity index 71%
rename from e2e/paths/05-ticket/20_future.spec.js
rename to e2e/paths/05-ticket/21_future.spec.js
index 6db2bf4f0..45c39de86 100644
--- a/e2e/paths/05-ticket/20_future.spec.js
+++ b/e2e/paths/05-ticket/21_future.spec.js
@@ -16,9 +16,6 @@ describe('Ticket Future path', () => {
await browser.close();
});
- const now = new Date();
- const tomorrow = new Date(now.getDate() + 1);
-
it('should show errors snackbar because of the required data', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.warehouseFk);
@@ -27,20 +24,6 @@ describe('Ticket Future path', () => {
expect(message.text).toContain('warehouseFk is a required argument');
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.litersMax);
- await page.waitToClick(selectors.ticketFuture.submit);
- message = await page.waitForSnackbar();
-
- expect(message.text).toContain('litersMax is a required argument');
-
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.linesMax);
- await page.waitToClick(selectors.ticketFuture.submit);
- message = await page.waitForSnackbar();
-
- expect(message.text).toContain('linesMax is a required argument');
-
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
await page.clearInput(selectors.ticketFuture.futureDated);
await page.waitToClick(selectors.ticketFuture.submit);
@@ -62,44 +45,13 @@ describe('Ticket Future path', () => {
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
});
- it('should search with the origin shipped today', async() => {
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.pickDate(selectors.ticketFuture.shipped, now);
- await page.waitToClick(selectors.ticketFuture.submit);
- await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
- });
-
- it('should search with the origin shipped tomorrow', async() => {
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.pickDate(selectors.ticketFuture.shipped, tomorrow);
- await page.waitToClick(selectors.ticketFuture.submit);
- await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
- });
-
- it('should search with the destination shipped today', async() => {
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.pickDate(selectors.ticketFuture.tfShipped, now);
- await page.waitToClick(selectors.ticketFuture.submit);
- await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
- });
-
- it('should search with the destination shipped tomorrow', async() => {
- await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.pickDate(selectors.ticketFuture.tfShipped, tomorrow);
- await page.waitToClick(selectors.ticketFuture.submit);
- await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
- });
-
it('should search with the origin IPT', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt);
- await page.clearInput(selectors.ticketFuture.tfIpt);
+ await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state);
- await page.clearInput(selectors.ticketFuture.tfState);
+ await page.clearInput(selectors.ticketFuture.futureState);
await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal');
await page.waitToClick(selectors.ticketFuture.submit);
@@ -109,14 +61,12 @@ describe('Ticket Future path', () => {
it('should search with the destination IPT', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt);
- await page.clearInput(selectors.ticketFuture.tfIpt);
+ await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state);
- await page.clearInput(selectors.ticketFuture.tfState);
+ await page.clearInput(selectors.ticketFuture.futureState);
- await page.autocompleteSearch(selectors.ticketFuture.tfIpt, 'Horizontal');
+ await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'Horizontal');
await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
});
@@ -124,12 +74,10 @@ describe('Ticket Future path', () => {
it('should search with the origin grouped state', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt);
- await page.clearInput(selectors.ticketFuture.tfIpt);
+ await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state);
- await page.clearInput(selectors.ticketFuture.tfState);
+ await page.clearInput(selectors.ticketFuture.futureState);
await page.autocompleteSearch(selectors.ticketFuture.state, 'Free');
await page.waitToClick(selectors.ticketFuture.submit);
@@ -139,24 +87,20 @@ describe('Ticket Future path', () => {
it('should search with the destination grouped state', async() => {
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt);
- await page.clearInput(selectors.ticketFuture.tfIpt);
+ await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state);
- await page.clearInput(selectors.ticketFuture.tfState);
+ await page.clearInput(selectors.ticketFuture.futureState);
- await page.autocompleteSearch(selectors.ticketFuture.tfState, 'Free');
+ await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free');
await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
- await page.clearInput(selectors.ticketFuture.shipped);
- await page.clearInput(selectors.ticketFuture.tfShipped);
await page.clearInput(selectors.ticketFuture.ipt);
- await page.clearInput(selectors.ticketFuture.tfIpt);
+ await page.clearInput(selectors.ticketFuture.futureIpt);
await page.clearInput(selectors.ticketFuture.state);
- await page.clearInput(selectors.ticketFuture.tfState);
+ await page.clearInput(selectors.ticketFuture.futureState);
await page.waitToClick(selectors.ticketFuture.submit);
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
@@ -176,7 +120,7 @@ describe('Ticket Future path', () => {
it('should search in smart-table with an ID Destination', async() => {
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
- await page.write(selectors.ticketFuture.tableTfId, '12');
+ await page.write(selectors.ticketFuture.tableFutureId, '12');
await page.keyboard.press('Enter');
await page.waitForNumberOfElements(selectors.ticketFuture.table, 5);
@@ -199,7 +143,7 @@ describe('Ticket Future path', () => {
it('should search in smart-table with an IPT Destination', async() => {
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
- await page.autocompleteSearch(selectors.ticketFuture.tableTfIpt, 'Vertical');
+ await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'Vertical');
await page.waitForNumberOfElements(selectors.ticketFuture.table, 1);
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
diff --git a/front/core/components/smart-table/index.js b/front/core/components/smart-table/index.js
index 8d2c3c153..770dcdf32 100644
--- a/front/core/components/smart-table/index.js
+++ b/front/core/components/smart-table/index.js
@@ -147,7 +147,7 @@ export default class SmartTable extends Component {
for (const column of this.columns) {
if (viewConfig.configuration[column.field] == false) {
const baseSelector = `smart-table[view-config-id="${this.viewConfigId}"] table`;
- selectors.push(`${baseSelector} thead > tr > th:nth-child(${column.index + 1})`);
+ selectors.push(`${baseSelector} thead > tr:not([second-header]) > th:nth-child(${column.index + 1})`);
selectors.push(`${baseSelector} tbody > tr > td:nth-child(${column.index + 1})`);
}
}
@@ -235,7 +235,7 @@ export default class SmartTable extends Component {
}
registerColumns() {
- const header = this.element.querySelector('thead > tr');
+ const header = this.element.querySelector('thead > tr:not([second-header])');
if (!header) return;
const columns = header.querySelectorAll('th');
@@ -254,7 +254,7 @@ export default class SmartTable extends Component {
}
emptyDataRows() {
- const header = this.element.querySelector('thead > tr');
+ const header = this.element.querySelector('thead > tr:not([second-header])');
const columns = header.querySelectorAll('th');
const tbody = this.element.querySelector('tbody');
if (tbody) {
@@ -333,7 +333,7 @@ export default class SmartTable extends Component {
}
displaySearch() {
- const header = this.element.querySelector('thead > tr');
+ const header = this.element.querySelector('thead > tr:not([second-header])');
if (!header) return;
const tbody = this.element.querySelector('tbody');
diff --git a/front/core/components/smart-table/table.scss b/front/core/components/smart-table/table.scss
index c38c149ca..996c41a74 100644
--- a/front/core/components/smart-table/table.scss
+++ b/front/core/components/smart-table/table.scss
@@ -8,6 +8,16 @@ smart-table table {
& > thead {
border-bottom: $border;
+ & > tr[second-header] {
+ & > th
+ {
+ text-align: center;
+ border-bottom-style: groove;
+ font-weight: bold;
+ text-transform: uppercase;
+ }
+ }
+
& > * > th {
font-weight: normal;
}
@@ -60,6 +70,9 @@ smart-table table {
vertical-align: middle;
}
}
+ &[separator]{
+ border-left-style: groove;
+ }
vn-icon.bright, i.bright {
color: #f7931e;
}
@@ -108,4 +121,4 @@ smart-table table {
font-size: 1.375rem;
text-align: center;
}
-}
\ No newline at end of file
+}
diff --git a/front/salix/components/app/app.html b/front/salix/components/app/app.html
index f14fab2dd..d32c9f68b 100644
--- a/front/salix/components/app/app.html
+++ b/front/salix/components/app/app.html
@@ -1,8 +1,9 @@
-
-
+
diff --git a/front/salix/components/app/app.js b/front/salix/components/app/app.js
index 20f0ad969..91a8d2215 100644
--- a/front/salix/components/app/app.js
+++ b/front/salix/components/app/app.js
@@ -21,7 +21,7 @@ export default class App extends Component {
get showLayout() {
const state = this.$state.current.name || this.$location.$$path.substring(1).replace('/', '.');
- const outLayout = ['login', 'recoverPassword', 'resetPassword'];
+ const outLayout = ['login', 'recoverPassword', 'resetPassword', 'reset-password'];
return state && !outLayout.some(ol => ol == state);
}
diff --git a/front/salix/components/index.js b/front/salix/components/index.js
index dbe9fe81a..3bd24d32f 100644
--- a/front/salix/components/index.js
+++ b/front/salix/components/index.js
@@ -19,3 +19,4 @@ import './user-popover';
import './upload-photo';
import './bank-entity';
import './log';
+import './sendSms';
diff --git a/front/salix/components/login/login.html b/front/salix/components/login/login.html
index a078fa0af..807e4b284 100644
--- a/front/salix/components/login/login.html
+++ b/front/salix/components/login/login.html
@@ -1,27 +1,32 @@
-
-
-
-
-
-
-
-
-
+
diff --git a/modules/client/front/descriptor/index.js b/modules/client/front/descriptor/index.js
index 4a0d1cd2a..4d8d70edf 100644
--- a/modules/client/front/descriptor/index.js
+++ b/modules/client/front/descriptor/index.js
@@ -39,6 +39,11 @@ class Controller extends Descriptor {
};
this.$.sms.open();
}
+
+ onSmsSend(sms) {
+ return this.$http.post(`Clients/${this.id}/sendSms`, sms)
+ .then(() => this.vnApp.showSuccess(this.$t('SMS sent')));
+ }
}
ngModule.vnComponent('vnClientDescriptor', {
diff --git a/modules/client/front/index.js b/modules/client/front/index.js
index a5782c789..ff767bc9e 100644
--- a/modules/client/front/index.js
+++ b/modules/client/front/index.js
@@ -35,7 +35,6 @@ import './sample/index';
import './sample/create';
import './web-payment';
import './log';
-import './sms';
import './postcode';
import './postcode/province';
import './postcode/city';
diff --git a/modules/client/front/sms/index.js b/modules/client/front/sms/index.js
deleted file mode 100644
index 701ee39af..000000000
--- a/modules/client/front/sms/index.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import ngModule from '../module';
-import Section from 'salix/components/section';
-import './style.scss';
-
-class Controller extends Section {
- open() {
- this.$.SMSDialog.show();
- }
-
- charactersRemaining() {
- const element = this.$.message;
- const value = element.input.value;
-
- const maxLength = 160;
- const textAreaLength = new Blob([value]).size;
- return maxLength - textAreaLength;
- }
-
- onResponse() {
- try {
- if (!this.sms.destination)
- throw new Error(`The destination can't be empty`);
- if (!this.sms.message)
- throw new Error(`The message can't be empty`);
- if (this.charactersRemaining() < 0)
- throw new Error(`The message it's too long`);
-
- this.$http.post(`Clients/${this.$params.id}/sendSms`, this.sms).then(res => {
- this.vnApp.showMessage(this.$t('SMS sent!'));
-
- if (res.data) this.emit('send', {response: res.data});
- });
- } catch (e) {
- this.vnApp.showError(this.$t(e.message));
- return false;
- }
- return true;
- }
-}
-
-Controller.$inject = ['$element', '$scope', '$http', '$translate', 'vnApp'];
-
-ngModule.vnComponent('vnClientSms', {
- template: require('./index.html'),
- controller: Controller,
- bindings: {
- sms: '<',
- }
-});
diff --git a/modules/client/front/sms/index.spec.js b/modules/client/front/sms/index.spec.js
deleted file mode 100644
index 793c80d6e..000000000
--- a/modules/client/front/sms/index.spec.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import './index';
-
-describe('Client', () => {
- describe('Component vnClientSms', () => {
- let controller;
- let $httpBackend;
- let $element;
-
- beforeEach(ngModule('client'));
-
- beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
- $httpBackend = _$httpBackend_;
- let $scope = $rootScope.$new();
- $element = angular.element('');
- controller = $componentController('vnClientSms', {$element, $scope});
- controller.client = {id: 1101};
- controller.$params = {id: 1101};
- controller.$.message = {
- input: {
- value: 'My SMS'
- }
- };
- }));
-
- describe('onResponse()', () => {
- it('should perform a POST query and show a success snackbar', () => {
- let params = {destinationFk: 1101, destination: 111111111, message: 'My SMS'};
- controller.sms = {destinationFk: 1101, destination: 111111111, message: 'My SMS'};
-
- jest.spyOn(controller.vnApp, 'showMessage');
- $httpBackend.expect('POST', `Clients/1101/sendSms`, params).respond(200, params);
-
- controller.onResponse();
- $httpBackend.flush();
-
- expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent!');
- });
-
- it('should call onResponse without the destination and show an error snackbar', () => {
- controller.sms = {destinationFk: 1101, message: 'My SMS'};
-
- jest.spyOn(controller.vnApp, 'showError');
-
- controller.onResponse('accept');
-
- expect(controller.vnApp.showError).toHaveBeenCalledWith(`The destination can't be empty`);
- });
-
- it('should call onResponse without the message and show an error snackbar', () => {
- controller.sms = {destinationFk: 1101, destination: 222222222};
-
- jest.spyOn(controller.vnApp, 'showError');
-
- controller.onResponse('accept');
-
- expect(controller.vnApp.showError).toHaveBeenCalledWith(`The message can't be empty`);
- });
- });
-
- describe('charactersRemaining()', () => {
- it('should return the characters remaining in a element', () => {
- controller.$.message = {
- input: {
- value: 'My message 0€'
- }
- };
-
- let result = controller.charactersRemaining();
-
- expect(result).toEqual(145);
- });
- });
- });
-});
diff --git a/modules/ticket/back/locale/ticket/en.yml b/modules/ticket/back/locale/ticket/en.yml
index 4e97f5d8c..c4ad84232 100644
--- a/modules/ticket/back/locale/ticket/en.yml
+++ b/modules/ticket/back/locale/ticket/en.yml
@@ -20,3 +20,4 @@ routeFk: route
companyFk: company
agencyModeFk: agency
ticketFk: ticket
+mergedTicket: merged ticket
diff --git a/modules/ticket/back/locale/ticket/es.yml b/modules/ticket/back/locale/ticket/es.yml
index a570f1f11..2c524a74f 100644
--- a/modules/ticket/back/locale/ticket/es.yml
+++ b/modules/ticket/back/locale/ticket/es.yml
@@ -20,3 +20,4 @@ routeFk: ruta
companyFk: empresa
agencyModeFk: agencia
ticketFk: ticket
+mergedTicket: ticket fusionado
diff --git a/modules/ticket/back/methods/ticket-future/getTicketsFuture.js b/modules/ticket/back/methods/ticket/getTicketsFuture.js
similarity index 69%
rename from modules/ticket/back/methods/ticket-future/getTicketsFuture.js
rename to modules/ticket/back/methods/ticket/getTicketsFuture.js
index 0fcc21182..6798df513 100644
--- a/modules/ticket/back/methods/ticket-future/getTicketsFuture.js
+++ b/modules/ticket/back/methods/ticket/getTicketsFuture.js
@@ -20,18 +20,6 @@ module.exports = Self => {
description: 'The date to probe',
required: true
},
- {
- arg: 'litersMax',
- type: 'number',
- description: 'Maximum volume of tickets to catapult',
- required: true
- },
- {
- arg: 'linesMax',
- type: 'number',
- description: 'Maximum number of lines of tickets to catapult',
- required: true
- },
{
arg: 'warehouseFk',
type: 'number',
@@ -39,15 +27,15 @@ module.exports = Self => {
required: true
},
{
- arg: 'shipped',
- type: 'date',
- description: 'Origin shipped',
+ arg: 'litersMax',
+ type: 'number',
+ description: 'Maximum volume of tickets to catapult',
required: false
},
{
- arg: 'tfShipped',
- type: 'date',
- description: 'Destination shipped',
+ arg: 'linesMax',
+ type: 'number',
+ description: 'Maximum number of lines of tickets to catapult',
required: false
},
{
@@ -57,7 +45,7 @@ module.exports = Self => {
required: false
},
{
- arg: 'tfIpt',
+ arg: 'futureIpt',
type: 'string',
description: 'Destination Item Packaging Type',
required: false
@@ -69,7 +57,7 @@ module.exports = Self => {
required: false
},
{
- arg: 'tfId',
+ arg: 'futureId',
type: 'number',
description: 'Destination id',
required: false
@@ -81,7 +69,7 @@ module.exports = Self => {
required: false
},
{
- arg: 'tfState',
+ arg: 'futureState',
type: 'string',
description: 'Destination state',
required: false
@@ -108,7 +96,7 @@ module.exports = Self => {
}
});
- Self.getTicketsFuture = async (ctx, options) => {
+ Self.getTicketsFuture = async(ctx, options) => {
const args = ctx.args;
const conn = Self.dataSource.connector;
const myOptions = {};
@@ -118,32 +106,32 @@ module.exports = Self => {
const where = buildFilter(ctx.args, (param, value) => {
switch (param) {
- case 'id':
- return { 'f.id': value };
- case 'tfId':
- return { 'f.ticketFuture': value };
- case 'shipped':
- return { 'f.shipped': value };
- case 'tfShipped':
- return { 'f.tfShipped': value };
- case 'ipt':
- return { 'f.ipt': value };
- case 'tfIpt':
- return { 'f.tfIpt': value };
- case 'state':
- return { 'f.code': { like: `%${value}%` } };
- case 'tfState':
- return { 'f.tfCode': { like: `%${value}%` } };
+ case 'id':
+ return {'f.id': value};
+ case 'lines':
+ return {'f.lines': {lte: value}};
+ case 'liters':
+ return {'f.liters': {lte: value}};
+ case 'futureId':
+ return {'f.futureId': value};
+ case 'ipt':
+ return {'f.ipt': value};
+ case 'futureIpt':
+ return {'f.futureIpt': value};
+ case 'state':
+ return {'f.stateCode': {like: `%${value}%`}};
+ case 'futureState':
+ return {'f.futureStateCode': {like: `%${value}%`}};
}
});
- let filter = mergeFilters(ctx.args.filter, { where });
+ let filter = mergeFilters(ctx.args.filter, {where});
const stmts = [];
let stmt;
stmt = new ParameterizedSQL(
- `CALL vn.ticket_canbePostponed(?,?,?,?,?)`,
- [args.originDated, args.futureDated, args.litersMax, args.linesMax, args.warehouseFk]);
+ `CALL vn.ticket_canbePostponed(?,?,?)`,
+ [args.originDated, args.futureDated, args.warehouseFk]);
stmts.push(stmt);
@@ -153,7 +141,7 @@ module.exports = Self => {
CREATE TEMPORARY TABLE tmp.sale_getProblems
(INDEX (ticketFk))
ENGINE = MEMORY
- SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped
+ SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped, f.lines, f.liters
FROM tmp.filter f
LEFT JOIN alertLevel al ON al.id = f.alertLevel
WHERE (al.code = 'FREE' OR f.alertLevel IS NULL)`);
@@ -174,35 +162,34 @@ module.exports = Self => {
let range;
let hasWhere;
switch (args.problems) {
- case true:
- condition = `or`;
- hasProblem = true;
- range = { neq: null };
- hasWhere = true;
- break;
+ case true:
+ condition = `or`;
+ hasProblem = true;
+ range = {neq: null};
+ hasWhere = true;
+ break;
- case false:
- condition = `and`;
- hasProblem = null;
- range = null;
- hasWhere = true;
- break;
+ case false:
+ condition = `and`;
+ hasProblem = null;
+ range = null;
+ hasWhere = true;
+ break;
}
const problems = {
[condition]: [
- { 'tp.isFreezed': hasProblem },
- { 'tp.risk': hasProblem },
- { 'tp.hasTicketRequest': hasProblem },
- { 'tp.itemShortage': range },
- { 'tp.hasComponentLack': hasProblem },
- { 'tp.isTooLittle': hasProblem }
+ {'tp.isFreezed': hasProblem},
+ {'tp.risk': hasProblem},
+ {'tp.hasTicketRequest': hasProblem},
+ {'tp.itemShortage': range},
+ {'tp.hasComponentLack': hasProblem},
+ {'tp.isTooLittle': hasProblem}
]
};
- if (hasWhere) {
- filter = mergeFilters(filter, { where: problems });
- }
+ if (hasWhere)
+ filter = mergeFilters(filter, {where: problems});
stmt.merge(conn.makeWhere(filter.where));
stmt.merge(conn.makeOrderBy(filter.order));
diff --git a/modules/ticket/back/methods/ticket/merge.js b/modules/ticket/back/methods/ticket/merge.js
index 04f8d83af..8aaca1085 100644
--- a/modules/ticket/back/methods/ticket/merge.js
+++ b/modules/ticket/back/methods/ticket/merge.js
@@ -40,19 +40,32 @@ module.exports = Self => {
try {
for (let ticket of tickets) {
- const fullPath = `${origin}/#!/ticket/${ticket.id}/summary`;
- const fullPathFuture = `${origin}/#!/ticket/${ticket.ticketFuture}/summary`;
+ const originFullPath = `${origin}/#!/ticket/${ticket.originId}/summary`;
+ const destinationFullPath = `${origin}/#!/ticket/${ticket.destinationId}/summary`;
const message = $t('Ticket merged', {
- originDated: dateUtil.toString(new Date(ticket.originETD)),
- futureDated: dateUtil.toString(new Date(ticket.destETD)),
- id: ticket.id,
- tfId: ticket.ticketFuture,
- fullPath,
- fullPathFuture
+ originDated: dateUtil.toString(new Date(ticket.originShipped)),
+ destinationDated: dateUtil.toString(new Date(ticket.destinationShipped)),
+ originId: ticket.originId,
+ destinationId: ticket.destinationId,
+ originFullPath,
+ destinationFullPath
});
- if (!ticket.id || !ticket.ticketFuture) continue;
- await models.Sale.updateAll({ticketFk: ticket.id}, {ticketFk: ticket.ticketFuture}, myOptions);
- await models.Ticket.setDeleted(ctx, ticket.id, myOptions);
+ if (!ticket.originId || !ticket.destinationId) continue;
+
+ const ticketDestinationLogRecord = {
+ originFk: ticket.destinationId,
+ userFk: ctx.req.accessToken.userId,
+ action: 'update',
+ changedModel: 'Ticket',
+ changedModelId: ticket.destinationId,
+ changedModelValue: ticket.destinationId,
+ oldInstance: {},
+ newInstance: {mergedTicket: ticket.originId}
+ };
+
+ await models.TicketLog.create(ticketDestinationLogRecord, myOptions);
+ await models.Sale.updateAll({ticketFk: ticket.originId}, {ticketFk: ticket.destinationId}, myOptions);
+ await models.Ticket.setDeleted(ctx, ticket.originId, myOptions);
await models.Chat.sendCheckingPresence(ctx, ticket.workerFk, message);
}
if (tx)
diff --git a/modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js b/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js
similarity index 53%
rename from modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js
rename to modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js
index 502ea3074..c05ba764d 100644
--- a/modules/ticket/back/methods/ticket-future/spec/getTicketsFuture.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/getTicketsFuture.spec.js
@@ -1,25 +1,22 @@
const models = require('vn-loopback/server/server').models;
-describe('TicketFuture getTicketsFuture()', () => {
+describe('ticket getTicketsFuture()', () => {
const today = new Date();
today.setHours(0, 0, 0, 0);
- const tomorrow = new Date(today.getDate() + 1);
- it('should return the tickets passing the required data', async () => {
+ it('should return the tickets passing the required data', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -30,22 +27,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the problems on true', async () => {
+ it('should return the tickets matching the problems on true', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
problems: true
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -57,22 +52,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the problems on false', async () => {
+ it('should return the tickets matching the problems on false', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
problems: false
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(0);
@@ -84,22 +77,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the problems on null', async () => {
+ it('should return the tickets matching the problems on null', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
problems: null
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -111,130 +102,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the correct origin shipped', async () => {
+ it('should return the tickets matching the OK State in origin date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
- shipped: today
+ state: 'OK'
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
- const result = await models.Ticket.getTicketsFuture(ctx, options);
-
- expect(result.length).toEqual(4);
-
- await tx.rollback();
- } catch (e) {
- await tx.rollback();
- throw e;
- }
- });
-
- it('should return the tickets matching the an incorrect origin shipped', async () => {
- const tx = await models.Ticket.beginTransaction({});
-
- try {
- const options = { transaction: tx };
-
- const args = {
- originDated: today,
- futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
- warehouseFk: 1,
- shipped: tomorrow
- };
-
- const ctx = { req: { accessToken: { userId: 9 } }, args };
- const result = await models.Ticket.getTicketsFuture(ctx, options);
-
- expect(result.length).toEqual(0);
-
- await tx.rollback();
- } catch (e) {
- await tx.rollback();
- throw e;
- }
- });
-
- it('should return the tickets matching the correct destination shipped', async () => {
- const tx = await models.Ticket.beginTransaction({});
-
- try {
- const options = { transaction: tx };
-
- const args = {
- originDated: today,
- futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
- warehouseFk: 1,
- tfShipped: today
- };
-
- const ctx = { req: { accessToken: { userId: 9 } }, args };
- const result = await models.Ticket.getTicketsFuture(ctx, options);
-
- expect(result.length).toEqual(4);
-
- await tx.rollback();
- } catch (e) {
- await tx.rollback();
- throw e;
- }
- });
-
- it('should return the tickets matching the an incorrect destination shipped', async () => {
- const tx = await models.Ticket.beginTransaction({});
-
- try {
- const options = { transaction: tx };
-
- const args = {
- originDated: today,
- futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
- warehouseFk: 1,
- tfShipped: tomorrow
- };
-
- const ctx = { req: { accessToken: { userId: 9 } }, args };
- const result = await models.Ticket.getTicketsFuture(ctx, options);
-
- expect(result.length).toEqual(0);
-
- await tx.rollback();
- } catch (e) {
- await tx.rollback();
- throw e;
- }
- });
-
- it('should return the tickets matching the OK State in origin date', async () => {
- const tx = await models.Ticket.beginTransaction({});
-
- try {
- const options = { transaction: tx };
-
- const args = {
- originDated: today,
- futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
- warehouseFk: 1,
- state: "OK"
- };
-
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(1);
@@ -246,22 +127,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the OK State in destination date', async () => {
+ it('should return the tickets matching the OK State in destination date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
- tfState: "OK"
+ futureState: 'OK'
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -273,22 +152,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the correct IPT in origin date', async () => {
+ it('should return the tickets matching the correct IPT in origin date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
ipt: null
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -300,22 +177,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the incorrect IPT in origin date', async () => {
+ it('should return the tickets matching the incorrect IPT in origin date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
ipt: 0
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(0);
@@ -327,22 +202,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the correct IPT in destination date', async () => {
+ it('should return the tickets matching the correct IPT in destination date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
- tfIpt: null
+ futureIpt: null
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -354,22 +227,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the incorrect IPT in destination date', async () => {
+ it('should return the tickets matching the incorrect IPT in destination date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
- tfIpt: 0
+ futureIpt: 0
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(0);
@@ -381,22 +252,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the ID in origin date', async () => {
+ it('should return the tickets matching the ID in origin date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
id: 13
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(1);
@@ -408,22 +277,20 @@ describe('TicketFuture getTicketsFuture()', () => {
}
});
- it('should return the tickets matching the ID in destination date', async () => {
+ it('should return the tickets matching the ID in destination date', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const args = {
originDated: today,
futureDated: today,
- litersMax: 9999,
- linesMax: 9999,
warehouseFk: 1,
- tfId: 12
+ futureId: 12
};
- const ctx = { req: { accessToken: { userId: 9 } }, args };
+ const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsFuture(ctx, options);
expect(result.length).toEqual(4);
@@ -434,5 +301,4 @@ describe('TicketFuture getTicketsFuture()', () => {
throw e;
}
});
-
});
diff --git a/modules/ticket/back/methods/ticket/specs/merge.spec.js b/modules/ticket/back/methods/ticket/specs/merge.spec.js
index 713f86ad6..275484f67 100644
--- a/modules/ticket/back/methods/ticket/specs/merge.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/merge.spec.js
@@ -3,15 +3,15 @@ const LoopBackContext = require('loopback-context');
describe('ticket merge()', () => {
const tickets = [{
- id: 13,
- ticketFuture: 12,
- workerFk: 1,
- originETD: new Date(),
- destETD: new Date()
+ originId: 13,
+ destinationId: 12,
+ originShipped: new Date(),
+ destinationShipped: new Date(),
+ workerFk: 1
}];
const activeCtx = {
- accessToken: { userId: 9 },
+ accessToken: {userId: 9},
};
beforeEach(() => {
@@ -22,26 +22,26 @@ describe('ticket merge()', () => {
const ctx = {
req: {
- accessToken: { userId: 9 },
- headers: { origin: 'http://localhost:5000' },
+ accessToken: {userId: 9},
+ headers: {origin: 'http://localhost:5000'},
}
};
ctx.req.__ = value => {
return value;
};
- it('should merge two tickets', async () => {
+ it('should merge two tickets', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
- const options = { transaction: tx };
+ const options = {transaction: tx};
const chatNotificationBeforeMerge = await models.Chat.find();
await models.Ticket.merge(ctx, tickets, options);
- const createdTicketLog = await models.TicketLog.find({ where: { originFk: tickets[0].id } }, options);
- const deletedTicket = await models.Ticket.findOne({ where: { id: tickets[0].id } }, options);
- const salesTicketFuture = await models.Sale.find({ where: { ticketFk: tickets[0].ticketFuture } }, options);
+ const createdTicketLog = await models.TicketLog.find({where: {originFk: tickets[0].originId}}, options);
+ const deletedTicket = await models.Ticket.findOne({where: {id: tickets[0].originId}}, options);
+ const salesTicketFuture = await models.Sale.find({where: {ticketFk: tickets[0].destinationId}}, options);
const chatNotificationAfterMerge = await models.Chat.find();
expect(createdTicketLog.length).toEqual(1);
diff --git a/modules/ticket/back/model-config.json b/modules/ticket/back/model-config.json
index baaca595e..17bd72949 100644
--- a/modules/ticket/back/model-config.json
+++ b/modules/ticket/back/model-config.json
@@ -94,8 +94,5 @@
},
"TicketConfig": {
"dataSource": "vn"
- },
- "TicketFuture": {
- "dataSource": "vn"
}
}
diff --git a/modules/ticket/back/models/ticket-future.json b/modules/ticket/back/models/ticket-future.json
deleted file mode 100644
index 00277ab8a..000000000
--- a/modules/ticket/back/models/ticket-future.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "name": "TicketFuture",
- "base": "PersistedModel",
- "acls": [
- {
- "accessType": "READ",
- "principalType": "ROLE",
- "principalId": "employee",
- "permission": "ALLOW"
- }
- ]
- }
diff --git a/modules/ticket/back/models/ticket-methods.js b/modules/ticket/back/models/ticket-methods.js
index 8fd74d35c..fe60cde8e 100644
--- a/modules/ticket/back/models/ticket-methods.js
+++ b/modules/ticket/back/models/ticket-methods.js
@@ -33,7 +33,7 @@ module.exports = function(Self) {
require('../methods/ticket/closeByTicket')(Self);
require('../methods/ticket/closeByAgency')(Self);
require('../methods/ticket/closeByRoute')(Self);
- require('../methods/ticket-future/getTicketsFuture')(Self);
+ require('../methods/ticket/getTicketsFuture')(Self);
require('../methods/ticket/merge')(Self);
require('../methods/ticket/isRoleAdvanced')(Self);
require('../methods/ticket/collectionLabel')(Self);
diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html
index 0c04b42fb..1f0ae8362 100644
--- a/modules/ticket/front/descriptor-menu/index.html
+++ b/modules/ticket/front/descriptor-menu/index.html
@@ -280,10 +280,11 @@
-
-
+
this.vnApp.showSuccess(this.$t('SMS sent')));
+ }
}
Controller.$inject = ['$element', '$scope', 'vnReport', 'vnEmail'];
diff --git a/modules/ticket/front/descriptor-menu/index.spec.js b/modules/ticket/front/descriptor-menu/index.spec.js
index 1716e36f6..f3d8ea3b3 100644
--- a/modules/ticket/front/descriptor-menu/index.spec.js
+++ b/modules/ticket/front/descriptor-menu/index.spec.js
@@ -261,11 +261,8 @@ describe('Ticket Component vnTicketDescriptorMenu', () => {
describe('showSMSDialog()', () => {
it('should set the destionationFk and destination properties and then call the sms open() method', () => {
controller.$.sms = {open: () => {}};
- jest.spyOn(controller.$.sms, 'open');
-
controller.showSMSDialog();
- expect(controller.$.sms.open).toHaveBeenCalledWith();
expect(controller.newSMS).toEqual({
destinationFk: ticket.clientFk,
destination: ticket.address.mobile,
diff --git a/modules/ticket/front/future-search-panel/index.html b/modules/ticket/front/future-search-panel/index.html
index 1b3ae453e..18b574f2a 100644
--- a/modules/ticket/front/future-search-panel/index.html
+++ b/modules/ticket/front/future-search-panel/index.html
@@ -4,43 +4,26 @@
+ ng-model="filter.originDated"
+ required="true">
-
-
-
-
-
-
+ required="true">
-
-
+ ng-model="filter.litersMax">
+
+
@@ -48,22 +31,22 @@
data="$ctrl.itemPackingTypes"
label="Origin IPT"
value-field="code"
- show-field="name"
+ show-field="description"
ng-model="filter.ipt"
info="IPT">
- {{name}}
+ {{description}}
- {{name}}
+ {{description}}
@@ -83,7 +66,7 @@
label="Destination Grouped State"
value-field="code"
show-field="name"
- ng-model="filter.tfState">
+ ng-model="filter.futureState">
{{name}}
diff --git a/modules/ticket/front/future-search-panel/index.js b/modules/ticket/front/future-search-panel/index.js
index 1a1f0e4c5..d7e7b3a5e 100644
--- a/modules/ticket/front/future-search-panel/index.js
+++ b/modules/ticket/front/future-search-panel/index.js
@@ -28,9 +28,8 @@ class Controller extends SearchPanel {
this.$http.get('ItemPackingTypes').then(res => {
for (let ipt of res.data) {
itemPackingTypes.push({
- id: ipt.id,
+ description: this.$t(ipt.description),
code: ipt.code,
- name: this.$t(ipt.code)
});
}
this.itemPackingTypes = itemPackingTypes;
diff --git a/modules/ticket/front/future-search-panel/locale/en.yml b/modules/ticket/front/future-search-panel/locale/en.yml
index fe71865cb..767c20152 100644
--- a/modules/ticket/front/future-search-panel/locale/en.yml
+++ b/modules/ticket/front/future-search-panel/locale/en.yml
@@ -1,9 +1 @@
Future tickets: Tickets a futuro
-FREE: Free
-DELIVERED: Delivered
-ON_PREPARATION: On preparation
-PACKED: Packed
-F: Fruits and vegetables
-V: Vertical
-H: Horizontal
-P: Feed
diff --git a/modules/ticket/front/future-search-panel/locale/es.yml b/modules/ticket/front/future-search-panel/locale/es.yml
index 82deba538..9d72c5b06 100644
--- a/modules/ticket/front/future-search-panel/locale/es.yml
+++ b/modules/ticket/front/future-search-panel/locale/es.yml
@@ -11,13 +11,4 @@ With problems: Con problemas
Warehouse: Almacén
Origin Grouped State: Estado agrupado origen
Destination Grouped State: Estado agrupado destino
-FREE: Libre
-DELIVERED: Servido
-ON_PREPARATION: En preparacion
-PACKED: Encajado
-F: Frutas y verduras
-V: Vertical
-H: Horizontal
-P: Pienso
-ETD: Tiempo estimado de entrega
IPT: Encajado
diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html
index d30cbaf19..1af1fb9ba 100644
--- a/modules/ticket/front/future/index.html
+++ b/modules/ticket/front/future/index.html
@@ -1,7 +1,7 @@
+ auto-load="false">
+
+ |
+ Origin |
+ Destination |
+
|
-
+ |
Problems
|
- Origin ID
+ ID
|
-
- Origin ETD
+ |
+ Date
+ |
+
+ IPT
|
- Origin State
+ State
|
-
- IPT
- |
-
+ |
Liters
|
-
+ |
Available Lines
|
-
- Destination ID
+ |
+ ID
|
-
- Destination ETD
+ |
+ Date
|
-
- Destination State
- |
-
+ |
IPT
|
+
+ State
+ |
@@ -125,38 +130,38 @@
{{::ticket.id}}
-
- {{::ticket.originETD | date: 'dd/MM/yyyy'}}
+
+ {{::ticket.shipped | date: 'dd/MM/yyyy'}}
|
+ {{::ticket.ipt}} |
{{::ticket.state}}
|
- {{::ticket.ipt}} |
{{::ticket.liters}} |
{{::ticket.lines}} |
- {{::ticket.ticketFuture}}
+ {{::ticket.futureId}}
|
-
- {{::ticket.destETD | date: 'dd/MM/yyyy'}}
+
+ {{::ticket.futureShipped | date: 'dd/MM/yyyy'}}
|
+ {{::ticket.futureIpt}} |
- {{::ticket.tfState}}
+ class="chip {{$ctrl.stateColor(ticket.futureState)}}">
+ {{::ticket.futureState}}
|
- {{::ticket.tfIpt}} |
diff --git a/modules/ticket/front/future/index.js b/modules/ticket/front/future/index.js
index 311b9c307..56ba1608e 100644
--- a/modules/ticket/front/future/index.js
+++ b/modules/ticket/front/future/index.js
@@ -11,15 +11,15 @@ export default class Controller extends Section {
search: true,
},
columns: [{
- field: 'problems',
+ field: 'totalProblems',
+ searchable: false,
+ },
+ {
+ field: 'shipped',
searchable: false
},
{
- field: 'originETD',
- searchable: false
- },
- {
- field: 'destETD',
+ field: 'futureShipped',
searchable: false
},
{
@@ -27,7 +27,7 @@ export default class Controller extends Section {
searchable: false
},
{
- field: 'tfState',
+ field: 'futureState',
searchable: false
},
{
@@ -39,7 +39,7 @@ export default class Controller extends Section {
}
},
{
- field: 'tfIpt',
+ field: 'futureIpt',
autocomplete: {
url: 'ItemPackingTypes',
showField: 'description',
@@ -48,6 +48,9 @@ export default class Controller extends Section {
},
]
};
+ }
+
+ $postLink() {
this.setDefaultFilter();
}
@@ -57,10 +60,9 @@ export default class Controller extends Section {
this.filterParams = {
originDated: today,
futureDated: today,
- linesMax: '9999',
- litersMax: '9999',
- warehouseFk: 1
+ warehouseFk: this.vnConfig.warehouseFk
};
+ this.$.model.applyFilter(null, this.filterParams);
}
compareDate(date) {
@@ -113,7 +115,17 @@ export default class Controller extends Section {
}
moveTicketsFuture() {
- let params = { tickets: this.checked };
+ let ticketsToMove = [];
+ this.checked.forEach(ticket => {
+ ticketsToMove.push({
+ originId: ticket.id,
+ destinationId: ticket.futureId,
+ originShipped: ticket.shipped,
+ destinationShipped: ticket.futureShipped,
+ workerFk: ticket.workerFk
+ });
+ });
+ let params = {tickets: ticketsToMove};
return this.$http.post('Tickets/merge', params)
.then(() => {
this.$.model.refresh();
@@ -123,18 +135,18 @@ export default class Controller extends Section {
exprBuilder(param, value) {
switch (param) {
- case 'id':
- return { 'id': value };
- case 'ticketFuture':
- return { 'ticketFuture': value };
- case 'litersMax':
- return { 'liters': value };
- case 'linesMax':
- return { 'lines': value };
- case 'ipt':
- return { 'ipt': value };
- case 'tfIpt':
- return { 'tfIpt': value };
+ case 'id':
+ return {'id': value};
+ case 'futureId':
+ return {'futureId': value};
+ case 'liters':
+ return {'liters': value};
+ case 'lines':
+ return {'lines': value};
+ case 'ipt':
+ return {'ipt': value};
+ case 'futureIpt':
+ return {'futureIpt': value};
}
}
}
diff --git a/modules/ticket/front/future/index.spec.js b/modules/ticket/front/future/index.spec.js
index 63deebc4f..c609a4891 100644
--- a/modules/ticket/front/future/index.spec.js
+++ b/modules/ticket/front/future/index.spec.js
@@ -2,33 +2,30 @@ import './index.js';
import crudModel from 'core/mocks/crud-model';
describe('Component vnTicketFuture', () => {
+ const today = new Date();
let controller;
let $httpBackend;
- let $window;
- beforeEach(ngModule('ticket')
- );
+ beforeEach(ngModule('ticket'));
- beforeEach(inject(($componentController, _$window_, _$httpBackend_) => {
+ beforeEach(inject(($componentController, _$httpBackend_) => {
$httpBackend = _$httpBackend_;
- $window = _$window_;
const $element = angular.element('');
- controller = $componentController('vnTicketFuture', { $element });
+ controller = $componentController('vnTicketFuture', {$element});
controller.$.model = crudModel;
controller.$.model.data = [{
id: 1,
checked: true,
- state: "OK"
+ state: 'OK'
}, {
id: 2,
checked: true,
- state: "Libre"
+ state: 'Libre'
}];
}));
describe('compareDate()', () => {
it('should return warning when the date is the present', () => {
- let today = new Date();
let result = controller.compareDate(today);
expect(result).toEqual('warning');
@@ -67,6 +64,7 @@ describe('Component vnTicketFuture', () => {
it('should return success to the OK tickets', () => {
const ok = controller.stateColor(controller.$.model.data[0].state);
const notOk = controller.stateColor(controller.$.model.data[1].state);
+
expect(ok).toEqual('success');
expect(notOk).not.toEqual('success');
});
@@ -74,6 +72,7 @@ describe('Component vnTicketFuture', () => {
it('should return success to the FREE tickets', () => {
const notFree = controller.stateColor(controller.$.model.data[0].state);
const free = controller.stateColor(controller.$.model.data[1].state);
+
expect(free).toEqual('notice');
expect(notFree).not.toEqual('notice');
});
@@ -81,18 +80,14 @@ describe('Component vnTicketFuture', () => {
describe('dateRange()', () => {
it('should return two dates with the hours at the start and end of the given date', () => {
- const now = new Date();
-
- const today = now.getDate();
-
- const dateRange = controller.dateRange(now);
+ const dateRange = controller.dateRange(today);
const start = dateRange[0].toString();
const end = dateRange[1].toString();
- expect(start).toContain(today);
+ expect(start).toContain(today.getDate());
expect(start).toContain('00:00:00');
- expect(end).toContain(today);
+ expect(end).toContain(today.getDate());
expect(end).toContain('23:59:59');
});
});
diff --git a/modules/ticket/front/future/locale/en.yml b/modules/ticket/front/future/locale/en.yml
index 66d3ce269..4400e6992 100644
--- a/modules/ticket/front/future/locale/en.yml
+++ b/modules/ticket/front/future/locale/en.yml
@@ -1,6 +1,2 @@
Move confirmation: Do you want to move {{checked}} tickets to the future?
-FREE: Free
-DELIVERED: Delivered
-ON_PREPARATION: On preparation
-PACKED: Packed
Success: Tickets moved successfully!
diff --git a/modules/ticket/front/future/locale/es.yml b/modules/ticket/front/future/locale/es.yml
index 9be0be6a4..9fceea111 100644
--- a/modules/ticket/front/future/locale/es.yml
+++ b/modules/ticket/front/future/locale/es.yml
@@ -3,20 +3,14 @@ Search tickets: Buscar tickets
Search future tickets by date: Buscar tickets por fecha
Problems: Problemas
Origin ID: ID origen
-Closing: Cierre
Origin State: Estado origen
Destination State: Estado destino
Liters: Litros
Available Lines: Líneas disponibles
Destination ID: ID destino
-Destination ETD: ETD Destino
-Origin ETD: ETD Origen
Move tickets: Mover tickets
Move confirmation: ¿Desea mover {{checked}} tickets hacia el futuro?
Success: Tickets movidos correctamente
-ETD: Tiempo estimado de entrega
IPT: Encajado
-FREE: Libre
-DELIVERED: Servido
-ON_PREPARATION: En preparacion
-PACKED: Encajado
+Origin Date: Fecha origen
+Destination Date: Fecha destino
diff --git a/modules/ticket/front/index.js b/modules/ticket/front/index.js
index 6106a22eb..b49c6d49b 100644
--- a/modules/ticket/front/index.js
+++ b/modules/ticket/front/index.js
@@ -32,7 +32,6 @@ import './weekly';
import './dms/index';
import './dms/create';
import './dms/edit';
-import './sms';
import './boxing';
import './future';
import './future-search-panel';
diff --git a/modules/ticket/front/sms/index.html b/modules/ticket/front/sms/index.html
deleted file mode 100644
index 97bdfef14..000000000
--- a/modules/ticket/front/sms/index.html
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{'Characters remaining' | translate}}:
-
- {{$ctrl.charactersRemaining()}}
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/modules/ticket/front/sms/index.spec.js b/modules/ticket/front/sms/index.spec.js
deleted file mode 100644
index b133db04d..000000000
--- a/modules/ticket/front/sms/index.spec.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import './index';
-
-describe('Ticket', () => {
- describe('Component vnTicketSms', () => {
- let controller;
- let $httpBackend;
-
- beforeEach(ngModule('ticket'));
-
- beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
- $httpBackend = _$httpBackend_;
- let $scope = $rootScope.$new();
- const $element = angular.element('');
- controller = $componentController('vnTicketSms', {$element, $scope});
- controller.$.message = {
- input: {
- value: 'My SMS'
- }
- };
- }));
-
- describe('onResponse()', () => {
- it('should perform a POST query and show a success snackbar', () => {
- let params = {ticketId: 11, destinationFk: 1101, destination: 111111111, message: 'My SMS'};
- controller.sms = {ticketId: 11, destinationFk: 1101, destination: 111111111, message: 'My SMS'};
-
- jest.spyOn(controller.vnApp, 'showMessage');
- $httpBackend.expect('POST', `Tickets/11/sendSms`, params).respond(200, params);
-
- controller.onResponse();
- $httpBackend.flush();
-
- expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent!');
- });
-
- it('should call onResponse without the destination and show an error snackbar', () => {
- controller.sms = {destinationFk: 1101, message: 'My SMS'};
-
- jest.spyOn(controller.vnApp, 'showError');
-
- controller.onResponse();
-
- expect(controller.vnApp.showError).toHaveBeenCalledWith(`The destination can't be empty`);
- });
-
- it('should call onResponse without the message and show an error snackbar', () => {
- controller.sms = {destinationFk: 1101, destination: 222222222};
-
- jest.spyOn(controller.vnApp, 'showError');
-
- controller.onResponse();
-
- expect(controller.vnApp.showError).toHaveBeenCalledWith(`The message can't be empty`);
- });
- });
-
- describe('charactersRemaining()', () => {
- it('should return the characters remaining in a element', () => {
- controller.$.message = {
- input: {
- value: 'My message 0€'
- }
- };
-
- let result = controller.charactersRemaining();
-
- expect(result).toEqual(145);
- });
- });
- });
-});
diff --git a/modules/ticket/front/sms/locale/es.yml b/modules/ticket/front/sms/locale/es.yml
deleted file mode 100644
index 64c3fcca6..000000000
--- a/modules/ticket/front/sms/locale/es.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-Send SMS: Enviar SMS
-Destination: Destinatario
-Message: Mensaje
-SMS sent!: ¡SMS enviado!
-Characters remaining: Carácteres restantes
-The destination can't be empty: El destinatario no puede estar vacio
-The message can't be empty: El mensaje no puede estar vacio
-The message it's too long: El mensaje es demasiado largo
-Special characters like accents counts as a multiple: Carácteres especiales como los acentos cuentan como varios
\ No newline at end of file
diff --git a/modules/ticket/front/sms/style.scss b/modules/ticket/front/sms/style.scss
deleted file mode 100644
index 84571a5f4..000000000
--- a/modules/ticket/front/sms/style.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-@import "variables";
-
-.SMSDialog {
- min-width: 400px
-}
\ No newline at end of file