diff --git a/db/changes/10180-holyWeek/00-ticketWeekly.sql b/db/changes/10180-holyWeek/00-ticketWeekly.sql
new file mode 100644
index 000000000..05d65e124
--- /dev/null
+++ b/db/changes/10180-holyWeek/00-ticketWeekly.sql
@@ -0,0 +1,13 @@
+ALTER TABLE `vn`.`ticketWeekly`
+ADD COLUMN `agencyModeFk` INT(11) NULL DEFAULT NULL AFTER `weekDay`,
+ADD INDEX `agencyModeFk_idx` (`agencyModeFk` ASC);
+
+ALTER TABLE `vn`.`ticketWeekly`
+ADD CONSTRAINT `agencyModeFk`
+ FOREIGN KEY (`agencyModeFk`)
+ REFERENCES `vn`.`agencyMode` (`id`)
+ ON DELETE SET NULL
+ ON UPDATE CASCADE;
+
+ALTER TABLE `vn`.`ticketWeekly`
+CHANGE COLUMN `weekDay` `weekDay` TINYINT(1) NOT NULL COMMENT 'funcion de mysql Lunes = 0, Domingo = 6' ;
diff --git a/db/changes/10180-holyWeek/00-ticket_cloneWeekly.sql b/db/changes/10180-holyWeek/00-ticket_cloneWeekly.sql
new file mode 100644
index 000000000..544296feb
--- /dev/null
+++ b/db/changes/10180-holyWeek/00-ticket_cloneWeekly.sql
@@ -0,0 +1,130 @@
+DELIMITER $$
+USE `vn`$$
+CREATE DEFINER=`root`@`%` PROCEDURE `ticket_cloneWeekly`(IN vWeek INT)
+BEGIN
+ DECLARE vIsDone BOOL;
+ DECLARE vLanding DATE;
+ DECLARE vShipment DATE;
+ DECLARE vWarehouse INT;
+ DECLARE vTicket INT;
+ DECLARE vWeekDay INT;
+ DECLARE vClient INT;
+ DECLARE vEmpresa INT;
+ DECLARE vAddressFk INT;
+ DECLARE vAgencyModeFk INT;
+ DECLARE vNewTicket INT;
+ DECLARE vYear INT;
+
+ DECLARE rsTicket CURSOR FOR
+ SELECT tw.ticketFk, weekDay, t.clientFk, t.warehouseFk, t.companyFk, t.addressFk, tw.agencyModeFk
+ FROM ticketWeekly tw
+ JOIN ticket t ON tt.ticketFk = t.id;
+
+ DECLARE CONTINUE HANDLER FOR NOT FOUND SET vIsDone = TRUE;
+
+ SET vYear = YEAR(CURDATE()) + IF(vWeek < WEEK(CURDATE()),1, 0);
+
+ OPEN rsTicket;
+
+ myLoop: LOOP
+ BEGIN
+ DECLARE vError TEXT;
+ DECLARE vSalesPersonEmail VARCHAR(150);
+ DECLARE vMailSent BOOL;
+ DECLARE vSubject VARCHAR(150);
+ DECLARE vMessage TEXT;
+ DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
+ BEGIN
+ GET DIAGNOSTICS CONDITION 1
+ vError = MESSAGE_TEXT;
+
+ END;
+
+ SET vIsDone = FALSE;
+ FETCH rsTicket INTO vTicket, vWeekDay, vClient, vWarehouse, vEmpresa, vAddressFk, vAgencyModeFk;
+
+ IF vIsDone THEN
+
+ LEAVE myLoop;
+ END IF;
+ SELECT date INTO vShipment
+ FROM `time`
+ WHERE `year` = vYear AND `week` = vWeek
+ AND WEEKDAY(date) = vWeekDay;
+
+ -- busca si el ticket ya ha sido clonado
+ IF (SELECT COUNT(*) FROM vn.ticket tOrig
+ JOIN vn.sale saleOrig ON tOrig.id = saleOrig.ticketFk
+ JOIN vn.saleCloned sc ON sc.saleOriginalFk = saleOrig.id
+ JOIN vn.sale saleClon ON saleClon.id = sc.saleClonedFk
+ JOIN vn.ticket tClon ON tClon.id = saleClon.ticketFk
+ WHERE tOrig.id = vTicket AND DATE(tClon.shipped) = vShipment) > 0
+ THEN
+ ITERATE myLoop;
+ END IF;
+ CALL vn.zone_getLanded(vShipment, vAddressFk, vAgencyModeFk, vWarehouse);
+
+ SELECT landed INTO vLanding from tmp.zoneGetLanded LIMIT 1;
+
+ CALL vn.ticketCreateWithoutZone(vClient, vShipment, vWarehouse, vEmpresa, vAddressFk, vAgencyModeFk, NULL, vLanding, account.userGetId(), vNewTicket);
+
+ IF (vLanding IS NULL) THEN
+
+ SELECT e.email INTO vSalesPersonEmail
+ FROM vn.client c
+ JOIN vn.worker sp ON sp.id = c.salesPersonFk
+ JOIN account.emailUser e ON e.userFk = sp.userFk
+ WHERE c.id = vClient;
+
+ SET vSubject = CONCAT('Turnos - No se ha podido clonar correctamente el ticket ', vTicket,
+ ' para el dia: ', vShipment);
+ SET vMessage = CONCAT('No se ha podido clonar el ticket ', vTicket,
+ ' para el dia: ', vShipment,
+ ' porque no hay una zona de envĂo disponible. Se ha creado el ticket: ', vNewTicket,
+ ' pero ha que revisar las fechas y la agencia');
+
+ SELECT COUNT(*) INTO vMailSent
+ FROM vn.mail
+ WHERE sender = vSalesPersonEmail
+ AND subject = vSubject;
+
+ IF NOT vMailSent THEN
+ INSERT INTO vn.mail (sender,`subject`,body)
+ VALUES (vSalesPersonEmail, vSubject, vMessage);
+ END IF;
+ CALL vn.ticketStateUpdate (vNewTicket, 'FIXING');
+ END IF;
+
+ INSERT INTO vn.sale (ticketFk, itemFk, concept, quantity, price, discount, priceFixed, isPriceFixed)
+ SELECT vNewTicket, saleOrig.itemFk , saleOrig.concept , saleOrig.quantity, saleOrig.price , saleOrig.discount, saleOrig.priceFixed, saleOrig.isPriceFixed
+ FROM vn.ticket tOrig
+ JOIN vn.sale saleOrig ON tOrig.id = saleOrig.ticketFk
+ LEFT JOIN vn.saleCloned sc ON sc.saleOriginalFk = saleOrig.id
+ LEFT JOIN vn.sale saleClon ON saleClon.id = sc.saleClonedFk
+ LEFT JOIN vn.ticket tClon ON tClon.id = saleClon.ticketFk AND DATE(tClon.shipped) = vShipment
+ WHERE tOrig.id = vTicket AND saleClon.id IS NULL;
+
+ INSERT IGNORE INTO vn.saleCloned(saleOriginalFk, saleClonedFk)
+ SELECT saleOriginal.id, saleClon.id
+ FROM vn.sale saleOriginal
+ JOIN vn.sale saleClon ON saleOriginal.itemFk = saleClon.itemFk AND saleOriginal.quantity = saleClon.quantity
+ WHERE saleOriginal.ticketFk = vTicket AND saleClon.ticketFk = vNewTicket;
+
+ INSERT INTO ticketRequest (description, ordered, shipped, salesPersonCode, buyerCode, quantity, price,
+ itemFk ,clientFk, response, total, buyed, saleFk)
+ SELECT tr.description, tr.ordered, tr.shipped, tr.salesPersonCode, tr.buyerCode, tr.quantity, tr.price,
+ tr.itemFk, tr.clientFk, tr.response, tr.total, tr.buyed, tr.saleFk
+ FROM sale s JOIN ticketRequest tr ON tr.saleFk = s.id
+ JOIN sale s2 ON s.concept = s2.concept AND s.quantity = s2.quantity AND m.Id_Article = m2.Id_Article
+ WHERE s.ticketFk = vTicket AND s2.ticketFk = vNewTicket;
+
+ CALL vn.ticketCalculateClon(vNewTicket, vTicket);
+ END;
+ END LOOP;
+
+ CLOSE rsTicket;
+
+END$$
+
+DELIMITER ;
+
diff --git a/db/changes/10180-holyWeek/01-migrateFromTicketToTicketWeekly.sql b/db/changes/10180-holyWeek/01-migrateFromTicketToTicketWeekly.sql
new file mode 100644
index 000000000..939a8e73c
--- /dev/null
+++ b/db/changes/10180-holyWeek/01-migrateFromTicketToTicketWeekly.sql
@@ -0,0 +1,6 @@
+UPDATE vn.ticketWeekly tw
+ JOIN vn.ticket t ON t.id = tw.ticketFk
+ JOIN vn.agencyMode am ON am.id = t.agencyModeFk
+SET tw.agencyModeFk = t.agencyModeFk
+WHERE am.name NOT LIKE '%turno%';
+
diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js
index c66fe415f..551573836 100644
--- a/e2e/helpers/selectors.js
+++ b/e2e/helpers/selectors.js
@@ -100,7 +100,6 @@ export default {
receivedCoreVNLCheckbox: 'vn-client-billing-data vn-check[label="Received core VNL"]',
receivedB2BVNLCheckbox: 'vn-client-billing-data vn-check[label="Received B2B VNL"]',
swiftBic: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.bankEntityFk"]',
- clearswiftBicButton: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.bankEntityFk"] .icons > vn-icon[icon=clear]',
newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button',
newBankEntityName: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newBankEntity.name"]',
newBankEntityBIC: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newBankEntity.bic"]',
@@ -379,11 +378,11 @@ export default {
topbarSearch: 'vn-searchbar',
advancedSearchButton: 'vn-ticket-search-panel button[type=submit]',
searchButton: 'vn-searchbar vn-icon[icon="search"]',
- searchWeeklyButton: 'vn-searchbar vn-icon[icon="search"]',
moreMenu: 'vn-ticket-index vn-icon-menu[icon=more_vert]',
sixthWeeklyTicket: 'vn-ticket-weekly-index vn-table vn-tr:nth-child(6)',
weeklyTicket: 'vn-ticket-weekly-index vn-table > div > vn-tbody > vn-tr',
firstWeeklyTicketDeleteIcon: 'vn-ticket-weekly-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
+ firstWeeklyTicketAgency: 'vn-ticket-weekly-index vn-tr:nth-child(1) [ng-model="weekly.agencyModeFk"]',
acceptDeleteTurn: '.vn-confirm.shown button[response="accept"]'
},
createTicketView: {
@@ -436,7 +435,6 @@ export default {
firstQuantity: 'vn-ticket-package vn-horizontal:nth-child(1) vn-input-number[ng-model="package.quantity"]',
firstRemovePackageButton: 'vn-icon-button[vn-tooltip="Remove package"]',
addPackageButton: 'vn-icon-button[vn-tooltip="Add package"]',
- clearPackageAutocompleteButton: 'vn-autocomplete[label="Package"] .icons > vn-icon[icon=clear]',
savePackagesButton: `button[type=submit]`
},
ticketSales: {
@@ -461,7 +459,6 @@ export default {
firstSaleZoomedImage: 'body > div > div > img',
firstSaleQuantity: 'vn-ticket-sale [ng-model="sale.quantity"]',
firstSaleQuantityCell: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td-editable:nth-child(5)',
- firstSaleQuantityClearInput: 'vn-textfield[ng-model="sale.quantity"] div.suffix > i',
firstSaleIdAutocomplete: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > vn-autocomplete',
firstSalePrice: 'vn-ticket-sale vn-table vn-tr:nth-child(1) > vn-td:nth-child(7) > span',
firstSalePriceInput: '.vn-popover.shown [ng-model="$ctrl.editedPrice"]',
@@ -491,7 +488,6 @@ export default {
deleteSaleButton: 'vn-ticket-sale vn-tool-bar > vn-button[icon="delete"]',
transferSaleButton: 'vn-ticket-sale vn-tool-bar > vn-button[icon="call_split"]',
moveToTicketInput: '.vn-popover.shown vn-textfield[ng-model="$ctrl.transfer.ticketId"]',
- moveToTicketInputClearButton: '.vn-popover.shown i[title="Clear"]',
moveToTicketButton: '.vn-popover.shown vn-icon[icon="arrow_forward_ios"]',
moveToNewTicketButton: '.vn-popover.shown vn-button[label="New ticket"]',
acceptDeleteLineButton: '.vn-confirm.shown button[response=accept]',
@@ -554,7 +550,6 @@ export default {
createStateView: {
state: 'vn-autocomplete[ng-model="$ctrl.stateFk"]',
worker: 'vn-autocomplete[ng-model="$ctrl.workerFk"]',
- clearStateInputButton: 'vn-autocomplete[ng-model="$ctrl.stateFk"] .icons > vn-icon[icon=clear]',
saveStateButton: `button[type=submit]`
},
claimsIndex: {
diff --git a/e2e/paths/05-ticket/09_weekly.spec.js b/e2e/paths/05-ticket/09_weekly.spec.js
index e0b6b8a30..9d59e9809 100644
--- a/e2e/paths/05-ticket/09_weekly.spec.js
+++ b/e2e/paths/05-ticket/09_weekly.spec.js
@@ -106,4 +106,16 @@ describe('Ticket descriptor path', () => {
expect(nResults).toEqual(5);
});
+
+ it('should update the agency then remove it afterwards', async() => {
+ await page.autocompleteSearch(selectors.ticketsIndex.firstWeeklyTicketAgency, 'Silla247');
+ let result = await page.waitForLastSnackbar();
+
+ expect(result).toEqual('Data saved!');
+
+ await page.clearInput(selectors.ticketsIndex.firstWeeklyTicketAgency);
+ result = await page.waitForLastSnackbar();
+
+ expect(result).toEqual('Data saved!');
+ });
});
diff --git a/modules/ticket/back/methods/ticket-weekly/filter.js b/modules/ticket/back/methods/ticket-weekly/filter.js
index 925dcdfac..77f8ecc57 100644
--- a/modules/ticket/back/methods/ticket-weekly/filter.js
+++ b/modules/ticket/back/methods/ticket-weekly/filter.js
@@ -51,16 +51,14 @@ module.exports = Self => {
stmt = new ParameterizedSQL(
`SELECT t.id AS ticketFk, c.id AS clientFk, c.name AS clientName, tw.weekDay,
- wh.name AS warehouseName, w.id AS workerFk, u.nickName
+ wh.name AS warehouseName, u.id AS workerFk, u.nickName, tw.agencyModeFk
FROM ticketWeekly tw
JOIN ticket t ON t.id = tw.ticketFk
JOIN client c ON c.id = t.clientFk
- JOIN worker w ON w.id = c.salesPersonFk
- JOIN account.user u ON u.id = w.userFk
+ JOIN account.user u ON u.id = c.salesPersonFk
JOIN warehouse wh ON wh.id = t.warehouseFk`
);
-
stmt.merge(conn.makeSuffix(filter));
let itemsIndex = stmts.push(stmt) - 1;
diff --git a/modules/ticket/back/models/ticket-weekly.js b/modules/ticket/back/models/ticket-weekly.js
index 733f1483a..8db53b283 100644
--- a/modules/ticket/back/models/ticket-weekly.js
+++ b/modules/ticket/back/models/ticket-weekly.js
@@ -3,14 +3,6 @@ const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
require('../methods/ticket-weekly/filter')(Self);
- Self.validatesPresenceOf('ticketFk', {
- message: `Ticket id cannot be blank`
- });
-
- Self.validatesPresenceOf('weekDay', {
- message: `Weekday cannot be blank`
- });
-
Self.rewriteDbError(function(err) {
if (err.code === 'ER_DUP_ENTRY')
return new UserError(`This ticket is already on weekly tickets`);
diff --git a/modules/ticket/back/models/ticket-weekly.json b/modules/ticket/back/models/ticket-weekly.json
index c19e79bc1..6d432831f 100644
--- a/modules/ticket/back/models/ticket-weekly.json
+++ b/modules/ticket/back/models/ticket-weekly.json
@@ -25,6 +25,11 @@
"type": "belongsTo",
"model": "Ticket",
"foreignKey": "ticketFk"
+ },
+ "agencyMode": {
+ "type": "belongsTo",
+ "model": "AgencyMode",
+ "foreignKey": "agencyModeFk"
}
}
}
\ No newline at end of file
diff --git a/modules/ticket/front/descriptor/index.js b/modules/ticket/front/descriptor/index.js
index 28fdfe3a2..5dc7a3f70 100644
--- a/modules/ticket/front/descriptor/index.js
+++ b/modules/ticket/front/descriptor/index.js
@@ -163,7 +163,10 @@ class Controller extends Component {
}
addTurn(day) {
- let params = {ticketFk: this.ticket.id, weekDay: day};
+ let params = {
+ ticketFk: this.ticket.id,
+ weekDay: day,
+ agencyModeFk: this.ticket.agencyModeFk};
this.$http.patch(`TicketWeeklies`, params).then(() => {
this.$.addTurn.hide();
this.vnApp.showSuccess(this.$t('Data saved!'));
diff --git a/modules/ticket/front/weekly/index.html b/modules/ticket/front/weekly/index.html
index 40ae04106..e97d47eef 100644
--- a/modules/ticket/front/weekly/index.html
+++ b/modules/ticket/front/weekly/index.html
@@ -25,6 +25,7 @@
Ticket ID
Client
Weekday
+ Agency
Warehouse
Salesperson
@@ -45,7 +46,7 @@
{{::weekly.clientName}}
-
+
+
+
+
+
{{::weekly.warehouseName}}
@@ -89,7 +102,7 @@
diff --git a/modules/ticket/front/weekly/index.js b/modules/ticket/front/weekly/index.js
index edc68aadb..a89dbbc2e 100644
--- a/modules/ticket/front/weekly/index.js
+++ b/modules/ticket/front/weekly/index.js
@@ -17,60 +17,44 @@ export default class Controller extends Section {
];
}
- onWeekdayUpdate(ticketFk, weekDay) {
- const params = {ticketFk, weekDay};
- this.$http.patch('TicketWeeklies/', params).then(() => {
- this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
+ onUpdate(ticketFk, field, value) {
+ const params = {ticketFk, [field]: value};
+ this.$http.patch('TicketWeeklies', params).then(() => {
+ this.vnApp.showSuccess(this.$t('Data saved!'));
});
}
- deleteWeekly(index) {
- this.ticketIndex = index;
- this.$.deleteWeekly.show();
- event.stopImmediatePropagation();
- }
-
showClientDescriptor(event, clientFk) {
this.$.clientDescriptor.clientFk = clientFk;
this.$.clientDescriptor.parent = event.target;
this.$.clientDescriptor.show();
- event.preventDefault();
- event.stopImmediatePropagation();
+ this.stopEvent(event);
}
showTicketDescriptor(event, ticketFk) {
this.$.ticketDescriptor.ticketFk = ticketFk;
this.$.ticketDescriptor.parent = event.target;
this.$.ticketDescriptor.show();
- event.preventDefault();
- event.stopImmediatePropagation();
+ this.stopEvent(event);
}
showWorkerDescriptor(event, workerFk) {
this.$.workerDescriptor.workerFk = workerFk;
this.$.workerDescriptor.parent = event.target;
this.$.workerDescriptor.show();
- event.preventDefault();
- event.stopImmediatePropagation();
+ this.stopEvent(event);
}
- onDescriptorLoad() {
- this.$.popover.relocate();
+ deleteWeekly(event, ticketFk) {
+ this.$.deleteWeekly.show(ticketFk);
+ this.stopEvent(event);
}
-
- preventNavigation(event) {
- event.preventDefault();
- event.stopImmediatePropagation();
- }
-
- returnDialog(response) {
- const ticket = this.$.model.data[this.ticketIndex];
- if (response === 'accept') {
- this.$http.delete(`TicketWeeklies/${ticket.ticketFk}`).then(() => {
- this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
- this.$.model.remove(this.ticketIndex);
- });
- }
+ onDeleteWeeklyAccept(ticketFk) {
+ return this.$http.delete(`TicketWeeklies/${ticketFk}`).then(() => {
+ this.vnApp.showSuccess(this.$t('Data saved!'));
+ const ticketIndex = this.$.model.data.findIndex(e => e.ticketFk == ticketFk);
+ this.$.model.remove(ticketIndex);
+ });
}
}
diff --git a/modules/ticket/front/weekly/index.spec.js b/modules/ticket/front/weekly/index.spec.js
new file mode 100644
index 000000000..a66e5c637
--- /dev/null
+++ b/modules/ticket/front/weekly/index.spec.js
@@ -0,0 +1,46 @@
+import './index';
+import crudModel from 'core/mocks/crud-model';
+
+describe('ticket weekly', () => {
+ describe('Component vnTicketWeeklyIndex', () => {
+ let controller;
+ let $httpBackend;
+
+ beforeEach(ngModule('ticket'));
+
+ beforeEach(angular.mock.inject(($componentController, _$httpBackend_, $rootScope) => {
+ $httpBackend = _$httpBackend_;
+ const $scope = $rootScope.$new();
+ const $element = angular.element('');
+ controller = $componentController('vnTicketWeeklyIndex', {$element, $scope});
+ }));
+
+ describe('onUpdate()', () => {
+ it('should make a query a PATCH querye then call vnApp.showSuccess()', () => {
+ jest.spyOn(controller.vnApp, 'showSuccess');
+
+ $httpBackend.expectPATCH(`TicketWeeklies`).respond();
+ controller.onUpdate('ticketFk', 'field', 'value');
+ $httpBackend.flush();
+
+ expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
+ });
+ });
+
+ describe('onDeleteWeeklyAccept()', () => {
+ it('should make a DELETE query then call showSuccess(), afterwards checks that remove returns value 0', () => {
+ controller.$.model = crudModel;
+ controller.$.model.data = [{ticketFk: 'ticketFk'}];
+ jest.spyOn(controller.vnApp, 'showSuccess');
+ jest.spyOn(controller.$.model, 'remove');
+
+ $httpBackend.expectDELETE(`TicketWeeklies/ticketFk`).respond();
+ controller.onDeleteWeeklyAccept('ticketFk');
+ $httpBackend.flush();
+
+ expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
+ expect(controller.$.model.remove).toHaveBeenCalledWith(0);
+ });
+ });
+ });
+});