Merge branch '#2174-ticket.weekly-añadir-campo-agencyModeFk' of verdnatura/salix into dev
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Juan Ferrer 2020-04-09 14:19:54 +00:00 committed by Gitea
commit 99813888ea
12 changed files with 252 additions and 55 deletions

View File

@ -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' ;

View File

@ -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 ;

View File

@ -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%';

View File

@ -99,7 +99,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"]',
@ -378,11 +377,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: {
@ -435,7 +434,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: {
@ -460,7 +458,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"]',
@ -490,7 +487,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]',
@ -553,7 +549,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: {

View File

@ -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!');
});
});

View File

@ -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;

View File

@ -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`);

View File

@ -25,6 +25,11 @@
"type": "belongsTo",
"model": "Ticket",
"foreignKey": "ticketFk"
},
"agencyMode": {
"type": "belongsTo",
"model": "AgencyMode",
"foreignKey": "agencyModeFk"
}
}
}

View File

@ -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!'));

View File

@ -25,6 +25,7 @@
<vn-th field="ticketFk" number>Ticket ID</vn-th>
<vn-th field="weekDay">Client</vn-th>
<vn-th>Weekday</vn-th>
<vn-th>Agency</vn-th>
<vn-th>Warehouse</vn-th>
<vn-th>Salesperson</vn-th>
<vn-th shrink></vn-th>
@ -45,7 +46,7 @@
{{::weekly.clientName}}
</span>
</vn-td>
<vn-td ng-click="$ctrl.preventNavigation($event)">
<vn-td ng-click="$ctrl.stopEvent($event)">
<vn-autocomplete
vn-one
vn-id="weekday"
@ -54,11 +55,23 @@
show-field="name"
translate-fields="['name']"
value-field="id"
on-change="$ctrl.onWeekdayUpdate(weekly.ticketFk, weekday.selection.id)"
on-change="$ctrl.onUpdate(weekly.ticketFk, 'weekDay', value)"
order="id"
class="dense">
</vn-autocomplete>
</vn-td>
<vn-td ng-click="$ctrl.stopEvent($event)">
<vn-autocomplete
vn-id="agencyMode"
ng-model="weekly.agencyModeFk"
url="AgencyModes/isActive"
show-field="name"
value-field="id"
on-change="$ctrl.onUpdate(weekly.ticketFk, 'agencyModeFk', value)"
order="name"
class="dense">
</vn-autocomplete>
</vn-td>
<vn-td>{{::weekly.warehouseName}}</vn-td>
<vn-td>
<span class="link"
@ -69,7 +82,7 @@
<vn-td shrink>
<vn-icon-button
icon="delete"
ng-click="$ctrl.deleteWeekly($index)"
ng-click="$ctrl.deleteWeekly($event, weekly.ticketFk)"
vn-tooltip="Delete">
</vn-icon-button>
</vn-td>
@ -89,7 +102,7 @@
</vn-worker-descriptor-popover>
<vn-confirm
vn-id="deleteWeekly"
on-response="$ctrl.returnDialog($response)"
on-accept="$ctrl.onDeleteWeeklyAccept($data)"
question="This ticket will be removed from weekly tickets! Continue anyway?"
message="You are going to delete this weekly ticket">
</vn-confirm>

View File

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

View File

@ -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('<vn-ticket-weekly-index></vn-ticket-weekly-index>');
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);
});
});
});
});