Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2973-module_zone_transactions
This commit is contained in:
commit
48a2bb7b10
|
@ -0,0 +1,103 @@
|
|||
DROP PROCEDURE IF EXISTS `vn`.`ticket_componentMakeUpdate`;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
|
||||
CREATE
|
||||
DEFINER = root@`%` PROCEDURE `vn`.`ticket_componentMakeUpdate`(IN vTicketFk INT, IN vClientFk INT,
|
||||
IN vNickname VARCHAR(50), IN vAgencyModeFk INT,
|
||||
IN vAddressFk INT, IN vZoneFk INT, IN vWarehouseFk TINYINT,
|
||||
IN vCompanyFk SMALLINT, IN vShipped DATETIME,
|
||||
IN vLanded DATE, IN vIsDeleted TINYINT(1),
|
||||
IN vHasToBeUnrouted TINYINT(1), IN vOption INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Modifica en el ticket los campos que se le pasan por parámetro
|
||||
* y cambia sus componentes
|
||||
*
|
||||
* @param vTicketFk Id del ticket a modificar
|
||||
* @param vClientFk nuevo cliente
|
||||
* @param vNickname nuevo alias
|
||||
* @param vAgencyModeFk nueva agencia
|
||||
* @param vAddressFk nuevo consignatario
|
||||
* @param vZoneFk nueva zona
|
||||
* @param vWarehouseFk nuevo almacen
|
||||
* @param vCompanyFk nueva empresa
|
||||
* @param vShipped nueva fecha del envio de mercancia
|
||||
* @param vLanded nueva fecha de recepcion de mercancia
|
||||
* @param vIsDeleted si se borra el ticket
|
||||
* @param vHasToBeUnrouted si se le elimina la ruta al ticket
|
||||
* @param vOption opcion para el case del proc ticketComponentUpdateSale
|
||||
*/
|
||||
DECLARE vPrice DECIMAL(10,2);
|
||||
DECLARE vBonus DECIMAL(10,2);
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
ROLLBACK;
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
CALL ticket_componentPreview (vTicketFk, vLanded, vAddressFk, vZoneFk, vWarehouseFk);
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
IF (SELECT addressFk FROM ticket WHERE id = vTicketFk) <> vAddressFk THEN
|
||||
|
||||
UPDATE ticket t
|
||||
JOIN address a ON a.id = vAddressFk
|
||||
SET t.nickname = a.nickname
|
||||
WHERE t.id = vTicketFk;
|
||||
|
||||
END IF;
|
||||
|
||||
CALL zone_getShippedWarehouse(vlanded, vAddressFk, vAgencyModeFk);
|
||||
|
||||
SELECT zoneFk, price, bonus INTO vZoneFk, vPrice, vBonus
|
||||
FROM tmp.zoneGetShipped
|
||||
WHERE shipped BETWEEN DATE(vShipped) AND util.dayEnd(vShipped) AND warehouseFk = vWarehouseFk LIMIT 1;
|
||||
|
||||
UPDATE ticket t
|
||||
SET
|
||||
t.clientFk = vClientFk,
|
||||
t.nickname = vNickname,
|
||||
t.agencyModeFk = vAgencyModeFk,
|
||||
t.addressFk = vAddressFk,
|
||||
t.zoneFk = vZoneFk,
|
||||
t.zonePrice = vPrice,
|
||||
t.zoneBonus = vBonus,
|
||||
t.warehouseFk = vWarehouseFk,
|
||||
t.companyFk = vCompanyFk,
|
||||
t.landed = vLanded,
|
||||
t.shipped = vShipped,
|
||||
t.isDeleted = vIsDeleted
|
||||
WHERE
|
||||
t.id = vTicketFk;
|
||||
|
||||
IF vHasToBeUnrouted THEN
|
||||
UPDATE ticket t SET t.routeFk = NULL
|
||||
WHERE t.id = vTicketFk;
|
||||
END IF;
|
||||
|
||||
IF vOption <> 8 THEN
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
|
||||
CREATE TEMPORARY TABLE tmp.sale
|
||||
(PRIMARY KEY (saleFk))
|
||||
ENGINE = MEMORY
|
||||
SELECT id AS saleFk, vWarehouseFk warehouseFk
|
||||
FROM sale s WHERE s.ticketFk = vTicketFk;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponent;
|
||||
CREATE TEMPORARY TABLE tmp.ticketComponent
|
||||
SELECT * FROM tmp.ticketComponentPreview;
|
||||
|
||||
CALL ticketComponentUpdateSale (vOption);
|
||||
|
||||
DROP TEMPORARY TABLE tmp.sale;
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponent;
|
||||
END IF;
|
||||
COMMIT;
|
||||
|
||||
DROP TEMPORARY TABLE tmp.zoneGetShipped, tmp.ticketComponentPreview;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
@ -837,7 +837,8 @@ export default {
|
|||
saveButton: 'vn-worker-pbx button[type=submit]'
|
||||
},
|
||||
workerTimeControl: {
|
||||
timeDialog: '.vn-dialog.shown vn-input-time[ng-model="$ctrl.newTime"]',
|
||||
dialogTimeInput: '.vn-dialog.shown vn-input-time[ng-model="$ctrl.newTimeEntry.timed"]',
|
||||
dialogTimeDirection: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.newTimeEntry.direction"]',
|
||||
mondayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(1) > vn-icon-button',
|
||||
tuesdayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(2) > vn-icon-button',
|
||||
wednesdayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(3) > vn-icon-button',
|
||||
|
@ -845,35 +846,35 @@ export default {
|
|||
fridayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(5) > vn-icon-button',
|
||||
saturdayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(6) > vn-icon-button',
|
||||
sundayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(7) > vn-icon-button',
|
||||
firstEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(1) > vn-chip > div',
|
||||
firstEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(1) > vn-chip > div',
|
||||
firstEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(1) > vn-chip > div',
|
||||
firstEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(1) > vn-chip > div',
|
||||
firstEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(1) > vn-chip > div',
|
||||
firstEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(1) > vn-chip > div',
|
||||
firstEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(1) > vn-chip > div',
|
||||
secondEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(2) > vn-chip > div',
|
||||
secondEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(2) > vn-chip > div',
|
||||
secondEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(2) > vn-chip > div',
|
||||
secondEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(2) > vn-chip > div',
|
||||
secondEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(2) > vn-chip > div',
|
||||
secondEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(2) > vn-chip > div',
|
||||
secondEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(2) > vn-chip > div',
|
||||
thirdEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(3) > vn-chip > div',
|
||||
firstEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(1) > vn-chip > div:nth-child(2)',
|
||||
firstEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(1) > vn-chip > div:nth-child(2)',
|
||||
firstEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(1) > vn-chip > div:nth-child(2)',
|
||||
firstEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(1) > vn-chip > div:nth-child(2)',
|
||||
firstEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(1) > vn-chip > div:nth-child(2)',
|
||||
firstEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(1) > vn-chip > div:nth-child(2)',
|
||||
firstEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(1) > vn-chip > div:nth-child(2)',
|
||||
secondEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(2) > vn-chip > div:nth-child(2)',
|
||||
secondEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(2) > vn-chip > div:nth-child(2)',
|
||||
secondEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(2) > vn-chip > div:nth-child(2)',
|
||||
secondEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(2) > vn-chip > div:nth-child(2)',
|
||||
secondEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(2) > vn-chip > div:nth-child(2)',
|
||||
secondEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(2) > vn-chip > div:nth-child(2)',
|
||||
secondEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(2) > vn-chip > div:nth-child(2)',
|
||||
thirdEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(3) > vn-chip > div:nth-child(2)',
|
||||
thirdEntryOfMondayDelete: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(3) > vn-chip > vn-icon[icon="cancel"]',
|
||||
thirdEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(3) > vn-chip > div',
|
||||
thirdEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(3) > vn-chip > div',
|
||||
thirdEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(3) > vn-chip > div',
|
||||
thirdEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(3) > vn-chip > div',
|
||||
thirdEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(3) > vn-chip > div',
|
||||
thirdEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(3) > vn-chip > div',
|
||||
fourthEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(4) > vn-chip > div',
|
||||
fourthEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(4) > vn-chip > div',
|
||||
fourthEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(4) > vn-chip > div',
|
||||
fourthEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(4) > vn-chip > div',
|
||||
fourthEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(4) > vn-chip > div',
|
||||
fourthEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(4) > vn-chip > div',
|
||||
fourthEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(4) > vn-chip > div',
|
||||
thirdEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(3) > vn-chip > div:nth-child(2)',
|
||||
thirdEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(3) > vn-chip > div:nth-child(2)',
|
||||
thirdEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(3) > vn-chip > div:nth-child(2)',
|
||||
thirdEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(3) > vn-chip > div:nth-child(2)',
|
||||
thirdEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(3) > vn-chip > div:nth-child(2)',
|
||||
thirdEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(3) > vn-chip > div:nth-child(2)',
|
||||
fourthEntryOfMonday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(4) > vn-chip > div:nth-child(2)',
|
||||
fourthEntryOfTuesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(2) > section:nth-child(4) > vn-chip > div:nth-child(2)',
|
||||
fourthEntryOfWednesday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(3) > section:nth-child(4) > vn-chip > div:nth-child(2)',
|
||||
fourthEntryOfThursday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(4) > section:nth-child(4) > vn-chip > div:nth-child(2)',
|
||||
fourthEntryOfFriday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(5) > section:nth-child(4) > vn-chip > div:nth-child(2)',
|
||||
fourthEntryOfSaturday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(6) > section:nth-child(4) > vn-chip > div:nth-child(2)',
|
||||
fourthEntryOfSunday: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(7) > section:nth-child(4) > vn-chip > div:nth-child(2)',
|
||||
mondayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(1)',
|
||||
tuesdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(2)',
|
||||
wednesdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(3)',
|
||||
|
|
|
@ -22,7 +22,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '07:00';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText');
|
||||
|
||||
|
@ -33,7 +34,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '10:00';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfMonday, 'innerText');
|
||||
|
||||
|
@ -44,7 +46,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '18:00';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.thirdEntryOfMonday, 'innerText');
|
||||
|
||||
|
@ -66,7 +69,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '14:00';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.thirdEntryOfMonday, 'innerText');
|
||||
|
||||
|
@ -77,7 +81,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '10:20';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.fourthEntryOfMonday, 'innerText');
|
||||
|
||||
|
@ -103,7 +108,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '08:00';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.tuesdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfTuesday, 'innerText');
|
||||
|
||||
|
@ -114,7 +120,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '10:00';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.tuesdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfTuesday, 'innerText');
|
||||
|
||||
|
@ -125,7 +132,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '10:20';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.tuesdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.thirdEntryOfTuesday, 'innerText');
|
||||
|
||||
|
@ -136,7 +144,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '16:00';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.tuesdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.fourthEntryOfTuesday, 'innerText');
|
||||
|
||||
|
@ -153,7 +162,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '09:00';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.wednesdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfWednesday, 'innerText');
|
||||
|
||||
|
@ -164,7 +174,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '10:00';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.wednesdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfWednesday, 'innerText');
|
||||
|
||||
|
@ -175,7 +186,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '10:20';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.wednesdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.thirdEntryOfWednesday, 'innerText');
|
||||
|
||||
|
@ -186,7 +198,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '17:00';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.wednesdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.fourthEntryOfWednesday, 'innerText');
|
||||
|
||||
|
@ -203,7 +216,8 @@ describe('Worker time control path', () => {
|
|||
const scanTime = '09:59';
|
||||
|
||||
await page.waitToClick(selectors.workerTimeControl.thursdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfThursday, 'innerText');
|
||||
|
||||
|
@ -213,7 +227,8 @@ describe('Worker time control path', () => {
|
|||
it(`should joyfully scan out Hank Pym for break`, async() => {
|
||||
const scanTime = '10:00';
|
||||
await page.waitToClick(selectors.workerTimeControl.thursdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfThursday, 'innerText');
|
||||
|
||||
|
@ -223,7 +238,8 @@ describe('Worker time control path', () => {
|
|||
it(`should joyfully scan in Hank Pym from the break`, async() => {
|
||||
const scanTime = '10:20';
|
||||
await page.waitToClick(selectors.workerTimeControl.thursdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.thirdEntryOfThursday, 'innerText');
|
||||
|
||||
|
@ -233,7 +249,8 @@ describe('Worker time control path', () => {
|
|||
it(`should joyfully scan out Hank Pym for the day`, async() => {
|
||||
const scanTime = '17:59';
|
||||
await page.waitToClick(selectors.workerTimeControl.thursdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.fourthEntryOfThursday, 'innerText');
|
||||
|
||||
|
@ -249,7 +266,8 @@ describe('Worker time control path', () => {
|
|||
it('should smilingly scan in Hank Pym', async() => {
|
||||
const scanTime = '07:30';
|
||||
await page.waitToClick(selectors.workerTimeControl.fridayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfFriday, 'innerText');
|
||||
|
||||
|
@ -259,7 +277,8 @@ describe('Worker time control path', () => {
|
|||
it(`should smilingly scan out Hank Pym for break`, async() => {
|
||||
const scanTime = '10:00';
|
||||
await page.waitToClick(selectors.workerTimeControl.fridayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfFriday, 'innerText');
|
||||
|
||||
|
@ -269,7 +288,8 @@ describe('Worker time control path', () => {
|
|||
it(`should smilingly scan in Hank Pym from the break`, async() => {
|
||||
const scanTime = '10:20';
|
||||
await page.waitToClick(selectors.workerTimeControl.fridayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.thirdEntryOfFriday, 'innerText');
|
||||
|
||||
|
@ -279,7 +299,8 @@ describe('Worker time control path', () => {
|
|||
it(`should smilingly scan out Hank Pym for the day`, async() => {
|
||||
const scanTime = '15:30';
|
||||
await page.waitToClick(selectors.workerTimeControl.fridayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.fourthEntryOfFriday, 'innerText');
|
||||
|
||||
|
@ -310,8 +331,10 @@ describe('Worker time control path', () => {
|
|||
|
||||
it('should lovingly scan in Hank Pym', async() => {
|
||||
const scanTime = '06:00';
|
||||
await page.waitForTimeout(1000); // without this timeout the dialog doesn't pop up
|
||||
await page.waitToClick(selectors.workerTimeControl.saturdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfSaturday, 'innerText');
|
||||
|
||||
|
@ -321,7 +344,8 @@ describe('Worker time control path', () => {
|
|||
it(`should lovingly scan out Hank Pym for the day with no break to leave a bit early`, async() => {
|
||||
const scanTime = '13:40';
|
||||
await page.waitToClick(selectors.workerTimeControl.saturdayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfSaturday, 'innerText');
|
||||
|
||||
|
@ -337,7 +361,8 @@ describe('Worker time control path', () => {
|
|||
it('should gladly scan in Hank Pym', async() => {
|
||||
const scanTime = '05:00';
|
||||
await page.waitToClick(selectors.workerTimeControl.sundayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfSunday, 'innerText');
|
||||
|
||||
|
@ -347,7 +372,8 @@ describe('Worker time control path', () => {
|
|||
it(`should gladly scan out Hank Pym for the day with no break to leave a bit early`, async() => {
|
||||
const scanTime = '12:40';
|
||||
await page.waitToClick(selectors.workerTimeControl.sundayAddTimeButton);
|
||||
await page.pickTime(selectors.workerTimeControl.timeDialog, scanTime);
|
||||
await page.pickTime(selectors.workerTimeControl.dialogTimeInput, scanTime);
|
||||
await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out');
|
||||
await page.respondToDialog('accept');
|
||||
const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfSunday, 'innerText');
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ describe('Account create and basic data path', () => {
|
|||
describe('Descriptor option', () => {
|
||||
describe('Edit role', () => {
|
||||
it('should edit the role using the descriptor menu', async() => {
|
||||
await page.waitForTimeout(1000); // sometimes descriptor fails to load it's functionalities without this timeout
|
||||
await page.waitToClick(selectors.accountDescriptor.menuButton);
|
||||
await page.waitToClick(selectors.accountDescriptor.changeRole);
|
||||
await page.autocompleteSearch(selectors.accountDescriptor.newRole, 'adminBoss');
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
<div
|
||||
ng-transclude="prepend"
|
||||
class="prepend"></div>
|
||||
<div ng-transclude></div>
|
||||
<div
|
||||
ng-transclude="append"
|
||||
class="append"></div>
|
||||
<vn-icon
|
||||
ng-click="$ctrl.onRemove()"
|
||||
ng-click="$ctrl.onRemove($event)"
|
||||
ng-if="$ctrl.removable"
|
||||
icon="cancel"
|
||||
tabindex="0">
|
||||
|
|
|
@ -3,16 +3,19 @@ import Component from '../../lib/component';
|
|||
import './style.scss';
|
||||
|
||||
export default class Chip extends Component {
|
||||
onRemove() {
|
||||
if (!this.disabled) this.emit('remove');
|
||||
onRemove($event) {
|
||||
if (!this.disabled) this.emit('remove', {$event});
|
||||
}
|
||||
}
|
||||
Chip.$inject = ['$element', '$scope', '$transclude'];
|
||||
|
||||
ngModule.vnComponent('vnChip', {
|
||||
template: require('./index.html'),
|
||||
transclude: {
|
||||
prepend: '?prepend',
|
||||
append: '?append'
|
||||
},
|
||||
controller: Chip,
|
||||
transclude: true,
|
||||
bindings: {
|
||||
disabled: '<?',
|
||||
removable: '<?'
|
||||
|
|
|
@ -18,9 +18,14 @@ describe('Component vnChip', () => {
|
|||
it(`should emit remove event`, () => {
|
||||
controller.emit = () => {};
|
||||
jest.spyOn(controller, 'emit');
|
||||
controller.onRemove();
|
||||
|
||||
expect(controller.emit).toHaveBeenCalledWith('remove');
|
||||
const $event = new Event('click');
|
||||
const target = document.createElement('div');
|
||||
target.dispatchEvent($event);
|
||||
|
||||
controller.onRemove($event);
|
||||
|
||||
expect(controller.emit).toHaveBeenCalledWith('remove', {$event});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@import "variables";
|
||||
@import "effects";
|
||||
|
||||
vn-chip {
|
||||
border-radius: 16px;
|
||||
|
@ -24,25 +25,47 @@ vn-chip {
|
|||
&.transparent {
|
||||
background-color: transparent;
|
||||
}
|
||||
&.colored {
|
||||
&.colored,
|
||||
&.colored.clickable:hover,
|
||||
&.colored.clickable:focus {
|
||||
background-color: $color-main;
|
||||
color: $color-font-bg;
|
||||
}
|
||||
&.notice {
|
||||
background-color: $color-notice-medium
|
||||
|
||||
&.notice,
|
||||
&.notice.clickable:hover,
|
||||
&.notice.clickable:focus {
|
||||
background-color: $color-notice-medium;
|
||||
}
|
||||
&.success {
|
||||
&.success,
|
||||
&.success.clickable:hover,
|
||||
&.success.clickable:focus {
|
||||
background-color: $color-success-medium;
|
||||
}
|
||||
&.warning {
|
||||
&.warning,
|
||||
&.warning.clickable:hover,
|
||||
&.warning.clickable:focus {
|
||||
background-color: $color-main-medium;
|
||||
}
|
||||
&.alert {
|
||||
&.alert,
|
||||
&.alert.clickable:hover,
|
||||
&.alert.clickable:focus {
|
||||
background-color: $color-alert-medium;
|
||||
}
|
||||
&.message {
|
||||
&.message,
|
||||
&.message.clickable:hover,
|
||||
&.message.clickable:focus {
|
||||
color: $color-font-dark;
|
||||
background-color: $color-bg-dark
|
||||
background-color: $color-bg-dark;
|
||||
}
|
||||
&.clickable {
|
||||
@extend %clickable;
|
||||
opacity: 0.8;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
& > div {
|
||||
|
@ -75,6 +98,20 @@ vn-chip {
|
|||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
& > .prepend {
|
||||
padding: 0 5px;
|
||||
padding-right: 0;
|
||||
|
||||
&:empty {display:none;}
|
||||
}
|
||||
& > .append {
|
||||
padding: 0 5px;
|
||||
padding-left: 0;
|
||||
|
||||
&:empty {display:none;}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
vn-avatar {
|
||||
|
|
|
@ -97,5 +97,6 @@
|
|||
"Role name must be written in camelCase": "Role name must be written in camelCase",
|
||||
"Client assignment has changed": "I did change the salesperson ~*\"<{{previousWorkerName}}>\"*~ by *\"<{{currentWorkerName}}>\"* from the client [{{clientName}} ({{clientId}})]({{{url}}})",
|
||||
"None": "None",
|
||||
"error densidad = 0": "error densidad = 0"
|
||||
"error densidad = 0": "error densidad = 0",
|
||||
"nickname": "nickname"
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
<vn-crud-model
|
||||
vn-id="ticketsModel"
|
||||
auto-load="true"
|
||||
url="Tickets/filter"
|
||||
link="{'t.clientFk': $ctrl.$params.id}"
|
||||
url="Tickets"
|
||||
link="{clientFk: $ctrl.$params.id}"
|
||||
filter="::$ctrl.ticketFilter"
|
||||
limit="5"
|
||||
data="tickets"
|
||||
order="shippedDate DESC, shippedHour ASC">
|
||||
order="shipped DESC">
|
||||
</vn-crud-model>
|
||||
<vn-card class="summary">
|
||||
<h5>
|
||||
|
@ -292,9 +293,9 @@
|
|||
<vn-tr>
|
||||
<vn-th field="id" number>Id</vn-th>
|
||||
<vn-th field="nickname" expand>Client</vn-th>
|
||||
<vn-th field="salesPersonFk">Salesperson</vn-th>
|
||||
<vn-th field="packages" shrink>Packages</vn-th>
|
||||
<vn-th field="shipped" shrink-date>Date</vn-th>
|
||||
<vn-th field="stateFk">State</vn-th>
|
||||
<vn-th>State</vn-th>
|
||||
<vn-th shrink>Total</vn-th>
|
||||
<vn-th></vn-th>
|
||||
</vn-tr>
|
||||
|
@ -312,13 +313,8 @@
|
|||
{{::ticket.nickname}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>
|
||||
<span
|
||||
title="{{::ticket.userName}}"
|
||||
vn-click-stop="workerDescriptor.show($event, ticket.salesPersonFk)"
|
||||
class="link">
|
||||
{{::ticket.userName | dashIfEmpty}}
|
||||
</span>
|
||||
<vn-td shrink>
|
||||
{{::ticket.packages}}
|
||||
</vn-td>
|
||||
<vn-td shrink-date>
|
||||
<span class="chip {{::$ctrl.chipColor(ticket.shipped)}}">
|
||||
|
@ -336,7 +332,7 @@
|
|||
<span
|
||||
ng-show="::!ticket.refFk"
|
||||
class="chip {{::$ctrl.stateColor(ticket)}}">
|
||||
{{::ticket.state}}
|
||||
{{::ticket.ticketState.state.name}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
|
|
|
@ -3,6 +3,21 @@ import Summary from 'salix/components/summary';
|
|||
import './style.scss';
|
||||
|
||||
class Controller extends Summary {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
|
||||
this.ticketFilter = {
|
||||
include: {
|
||||
relation: 'ticketState',
|
||||
scope: {
|
||||
fields: ['stateFk', 'code', 'alertLevel'],
|
||||
include: {
|
||||
relation: 'state'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
$onChanges() {
|
||||
if (!this.client)
|
||||
return;
|
||||
|
@ -18,6 +33,7 @@ class Controller extends Summary {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
get isEmployee() {
|
||||
return this.aclService.hasAny(['employee']);
|
||||
}
|
||||
|
@ -41,13 +57,15 @@ class Controller extends Summary {
|
|||
}
|
||||
|
||||
stateColor(ticket) {
|
||||
if (ticket.alertLevelCode === 'OK')
|
||||
const ticketState = ticket.ticketState;
|
||||
|
||||
if (ticketState.code === 'OK')
|
||||
return 'success';
|
||||
else if (ticket.alertLevelCode === 'FREE')
|
||||
else if (ticketState.code === 'FREE')
|
||||
return 'notice';
|
||||
else if (ticket.alertLevel === 1)
|
||||
else if (ticketState.alertLevel === 1)
|
||||
return 'warning';
|
||||
else if (ticket.alertLevel === 0)
|
||||
else if (ticketState.alertLevel === 0)
|
||||
return 'alert';
|
||||
}
|
||||
|
||||
|
|
|
@ -76,25 +76,25 @@ describe('Client', () => {
|
|||
|
||||
describe('stateColor()', () => {
|
||||
it('should return "success" when the alertLevelCode property is "OK"', () => {
|
||||
const result = controller.stateColor({alertLevelCode: 'OK'});
|
||||
const result = controller.stateColor({ticketState: {code: 'OK'}});
|
||||
|
||||
expect(result).toEqual('success');
|
||||
});
|
||||
|
||||
it('should return "notice" when the alertLevelCode property is "FREE"', () => {
|
||||
const result = controller.stateColor({alertLevelCode: 'FREE'});
|
||||
const result = controller.stateColor({ticketState: {code: 'FREE'}});
|
||||
|
||||
expect(result).toEqual('notice');
|
||||
});
|
||||
|
||||
it('should return "warning" when the alertLevel property is "1', () => {
|
||||
const result = controller.stateColor({alertLevel: 1});
|
||||
const result = controller.stateColor({ticketState: {code: 'PACKING', alertLevel: 1}});
|
||||
|
||||
expect(result).toEqual('warning');
|
||||
});
|
||||
|
||||
it('should return "alert" when the alertLevel property is "0"', () => {
|
||||
const result = controller.stateColor({alertLevel: 0});
|
||||
const result = controller.stateColor({ticketState: {code: 'FIXING', alertLevel: 0}});
|
||||
|
||||
expect(result).toEqual('alert');
|
||||
});
|
||||
|
|
|
@ -109,8 +109,9 @@ module.exports = Self => {
|
|||
return {'ii.created': {gte: value}};
|
||||
case 'to':
|
||||
return {'ii.created': {lte: value}};
|
||||
case 'account':
|
||||
case 'fi':
|
||||
return {'s.nif': value};
|
||||
case 'account':
|
||||
return {[`s.${param}`]: value};
|
||||
case 'supplierRef':
|
||||
case 'supplierFk':
|
||||
|
|
|
@ -54,19 +54,22 @@
|
|||
</vn-icon-button>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button
|
||||
<!-- <vn-icon-button
|
||||
ng-show="invoiceIn.dmsFk"
|
||||
vn-click-stop="$ctrl.openPdf(invoiceIn.dmsFk)"
|
||||
icon="cloud_download"
|
||||
title="Download PDF"
|
||||
vn-tooltip="Download PDF">
|
||||
</vn-icon-button>
|
||||
</vn-icon-button> -->
|
||||
</vn-td>
|
||||
</a>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-supplier-descriptor-popover
|
||||
vn-id="supplierDescriptor">
|
||||
</vn-supplier-descriptor-popover>
|
||||
<vn-popup vn-id="summary">
|
||||
<vn-invoice-in-summary
|
||||
invoice-in="$ctrl.selectedInvoiceIn">
|
||||
|
|
|
@ -27,11 +27,12 @@
|
|||
label="Account"
|
||||
ng-model="filter.account">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
<vn-input-number
|
||||
vn-one
|
||||
label="Amount"
|
||||
ng-model="filter.amount">
|
||||
</vn-textfield>
|
||||
ng-model="filter.amount"
|
||||
step="0.01">
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-date-picker
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<vn-td expand>{{::invoiceOut.created | date:'dd/MM/yyyy' | dashIfEmpty}}</vn-td>
|
||||
<vn-td>{{::invoiceOut.companyCode | dashIfEmpty}}</vn-td>
|
||||
<vn-td shrink>{{::invoiceOut.dued | date:'dd/MM/yyyy' | dashIfEmpty}}</vn-td>
|
||||
<vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button
|
||||
ng-show="invoiceOut.hasPdf"
|
||||
vn-click-stop="$ctrl.openPdf(invoiceOut.id)"
|
||||
|
@ -45,7 +45,7 @@
|
|||
vn-tooltip="Download PDF">
|
||||
</vn-icon-button>
|
||||
</vn-td>
|
||||
<vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-icon-button
|
||||
vn-click-stop="$ctrl.preview(invoiceOut)"
|
||||
vn-tooltip="Preview"
|
||||
|
|
|
@ -19,6 +19,11 @@ module.exports = Self => {
|
|||
description: 'The client id',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
arg: 'nickname',
|
||||
type: 'string',
|
||||
description: 'The client nickname'
|
||||
},
|
||||
{
|
||||
arg: 'agencyModeFk',
|
||||
type: 'number',
|
||||
|
@ -145,10 +150,11 @@ module.exports = Self => {
|
|||
|
||||
// Force to unroute ticket
|
||||
const hasToBeUnrouted = true;
|
||||
const query = 'CALL vn.ticket_componentMakeUpdate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
const query = 'CALL vn.ticket_componentMakeUpdate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
const res = await Self.rawSql(query, [
|
||||
args.id,
|
||||
args.clientFk,
|
||||
args.nickname,
|
||||
args.agencyModeFk,
|
||||
args.addressFk,
|
||||
args.zoneFk,
|
||||
|
|
|
@ -20,6 +20,16 @@
|
|||
initial-data="$ctrl.clientId"
|
||||
order="id">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
required="true"
|
||||
url="Warehouses"
|
||||
label="Warehouse"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
ng-model="$ctrl.warehouseId">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
required="true"
|
||||
|
@ -44,14 +54,12 @@
|
|||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Alias"
|
||||
required="true"
|
||||
url="Warehouses"
|
||||
label="Warehouse"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
ng-model="$ctrl.warehouseId">
|
||||
</vn-autocomplete>
|
||||
ng-model="$ctrl.ticket.nickname">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
|
|
|
@ -40,6 +40,7 @@ class Controller extends Component {
|
|||
set addressId(value) {
|
||||
if (value != this.ticket.addressFk) {
|
||||
this.ticket.addressFk = value;
|
||||
this.onChangeAddress(value);
|
||||
this.getShipped({
|
||||
landed: this.ticket.landed,
|
||||
addressFk: value,
|
||||
|
@ -179,6 +180,14 @@ class Controller extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
onChangeAddress(addressId) {
|
||||
this.ticket.nickname = null;
|
||||
const query = `Addresses/${addressId}`;
|
||||
this.$http.get(query).then(res => {
|
||||
this.ticket.nickname = res.data.nickname;
|
||||
});
|
||||
}
|
||||
|
||||
async onStepChange() {
|
||||
if (this.isFormInvalid()) {
|
||||
return this.vnApp.showError(
|
||||
|
|
|
@ -71,6 +71,7 @@ class Controller extends Component {
|
|||
let query = `tickets/${this.ticket.id}/componentUpdate`;
|
||||
let params = {
|
||||
clientFk: this.ticket.clientFk,
|
||||
nickname: this.ticket.nickname,
|
||||
agencyModeFk: this.ticket.agencyModeFk,
|
||||
addressFk: this.ticket.addressFk,
|
||||
zoneFk: this.ticket.zoneFk,
|
||||
|
|
|
@ -5,38 +5,54 @@ module.exports = Self => {
|
|||
description: 'Adds a new hour registry',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'data',
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'workerFk, timed',
|
||||
http: {source: 'body'}
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
description: 'The worker id',
|
||||
http: {source: 'path'}
|
||||
},
|
||||
{
|
||||
arg: 'timed',
|
||||
type: 'date',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
arg: 'direction',
|
||||
type: 'string',
|
||||
required: true
|
||||
}],
|
||||
returns: [{
|
||||
type: 'Object',
|
||||
root: true
|
||||
}],
|
||||
http: {
|
||||
path: `/addTimeEntry`,
|
||||
path: `/:id/addTimeEntry`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.addTimeEntry = async(ctx, data) => {
|
||||
const Worker = Self.app.models.Worker;
|
||||
const myUserId = ctx.req.accessToken.userId;
|
||||
const myWorker = await Worker.findOne({where: {userFk: myUserId}});
|
||||
const isSubordinate = await Worker.isSubordinate(ctx, data.workerFk);
|
||||
const isTeamBoss = await Self.app.models.Account.hasRole(myUserId, 'teamBoss');
|
||||
Self.addTimeEntry = async(ctx, workerId, options) => {
|
||||
const models = Self.app.models;
|
||||
const args = ctx.args;
|
||||
const currentUserId = ctx.req.accessToken.userId;
|
||||
|
||||
if (isSubordinate === false || (isSubordinate && myWorker.id == data.workerFk && !isTeamBoss))
|
||||
let myOptions = {};
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const isSubordinate = await models.Worker.isSubordinate(ctx, workerId, myOptions);
|
||||
const isTeamBoss = await models.Account.hasRole(currentUserId, 'teamBoss', myOptions);
|
||||
const isHimself = currentUserId == workerId;
|
||||
|
||||
if (isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss))
|
||||
throw new UserError(`You don't have enough privileges`);
|
||||
|
||||
const subordinate = await Worker.findById(data.workerFk);
|
||||
const timed = new Date(data.timed);
|
||||
const timed = new Date(args.timed);
|
||||
|
||||
let [result] = await Self.rawSql('SELECT vn.workerTimeControl_add(?, ?, ?, ?) AS id', [
|
||||
subordinate.userFk, null, timed, true]);
|
||||
|
||||
return result;
|
||||
return models.WorkerTimeControl.create({
|
||||
userFk: workerId,
|
||||
direction: args.direction,
|
||||
timed: timed,
|
||||
manual: true
|
||||
}, myOptions);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -21,21 +21,24 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.deleteTimeEntry = async(ctx, id) => {
|
||||
Self.deleteTimeEntry = async(ctx, id, options) => {
|
||||
const currentUserId = ctx.req.accessToken.userId;
|
||||
const workerModel = Self.app.models.Worker;
|
||||
const models = Self.app.models;
|
||||
|
||||
const targetTimeEntry = await Self.findById(id);
|
||||
const isSubordinate = await workerModel.isSubordinate(ctx, targetTimeEntry.userFk);
|
||||
const isTeamBoss = await Self.app.models.Account.hasRole(currentUserId, 'teamBoss');
|
||||
let myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const targetTimeEntry = await Self.findById(id, null, myOptions);
|
||||
const isSubordinate = await models.Worker.isSubordinate(ctx, targetTimeEntry.userFk, myOptions);
|
||||
const isTeamBoss = await models.Account.hasRole(currentUserId, 'teamBoss', myOptions);
|
||||
const isHimself = currentUserId == targetTimeEntry.userFk;
|
||||
|
||||
const notAllowed = isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss);
|
||||
|
||||
if (notAllowed)
|
||||
if (isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss))
|
||||
throw new UserError(`You don't have enough privileges`);
|
||||
|
||||
return Self.rawSql('CALL vn.workerTimeControl_remove(?, ?)', [
|
||||
targetTimeEntry.userFk, targetTimeEntry.timed]);
|
||||
targetTimeEntry.userFk, targetTimeEntry.timed], myOptions);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
const LoopBackContext = require('loopback-context');
|
||||
const models = app.models;
|
||||
|
||||
describe('workerTimeControl add/delete timeEntry()', () => {
|
||||
const HHRRId = 37;
|
||||
|
@ -12,19 +13,6 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
|||
};
|
||||
let ctx = {req: activeCtx};
|
||||
|
||||
let timeEntry;
|
||||
let createdTimeEntry;
|
||||
|
||||
afterEach(async() => {
|
||||
if (createdTimeEntry) {
|
||||
try {
|
||||
await app.models.WorkerTimeControl.destroyById(createdTimeEntry.id);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||
active: activeCtx
|
||||
|
@ -33,14 +21,13 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
|||
|
||||
it('should fail to add a time entry if the target user is not a subordinate', async() => {
|
||||
activeCtx.accessToken.userId = employeeId;
|
||||
const workerId = 2;
|
||||
|
||||
let error;
|
||||
let data = {
|
||||
workerFk: 2,
|
||||
timed: new Date()
|
||||
};
|
||||
|
||||
try {
|
||||
await app.models.WorkerTimeControl.addTimeEntry(ctx, data);
|
||||
ctx.args = {timed: new Date(), direction: 'in'};
|
||||
await models.WorkerTimeControl.addTimeEntry(ctx, workerId);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
@ -52,14 +39,12 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
|||
|
||||
it('should fail to add if the current and the target user are the same and is not team boss', async() => {
|
||||
activeCtx.accessToken.userId = employeeId;
|
||||
const workerId = employeeId;
|
||||
let error;
|
||||
let data = {
|
||||
workerFk: 1,
|
||||
timed: new Date()
|
||||
};
|
||||
|
||||
try {
|
||||
await app.models.WorkerTimeControl.addTimeEntry(ctx, data);
|
||||
ctx.args = {timed: new Date(), direction: 'in'};
|
||||
await models.WorkerTimeControl.addTimeEntry(ctx, workerId);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
@ -71,41 +56,49 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
|||
|
||||
it('should add if the current user is team boss and the target user is a himself', async() => {
|
||||
activeCtx.accessToken.userId = teamBossId;
|
||||
let todayAtSix = new Date();
|
||||
todayAtSix.setHours(18, 30, 0, 0);
|
||||
const workerId = teamBossId;
|
||||
|
||||
let data = {
|
||||
workerFk: teamBossId,
|
||||
timed: todayAtSix
|
||||
};
|
||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
timeEntry = await app.models.WorkerTimeControl.addTimeEntry(ctx, data);
|
||||
const todayAtSix = new Date();
|
||||
todayAtSix.setHours(18, 30, 0, 0);
|
||||
|
||||
createdTimeEntry = await app.models.WorkerTimeControl.findById(timeEntry.id);
|
||||
ctx.args = {timed: todayAtSix, direction: 'in'};
|
||||
const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||
|
||||
expect(createdTimeEntry).toBeDefined();
|
||||
expect(createdTimeEntry.id).toBeDefined();
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should try but fail to delete his own time entry', async() => {
|
||||
activeCtx.accessToken.userId = salesBossId;
|
||||
const workerId = salesBossId;
|
||||
|
||||
let error;
|
||||
let todayAtSeven = new Date();
|
||||
todayAtSeven.setHours(19, 30, 0, 0);
|
||||
|
||||
let data = {
|
||||
workerFk: salesPersonId,
|
||||
timed: todayAtSeven
|
||||
};
|
||||
|
||||
timeEntry = await app.models.WorkerTimeControl.addTimeEntry(ctx, data);
|
||||
|
||||
createdTimeEntry = await app.models.WorkerTimeControl.findById(timeEntry.id);
|
||||
|
||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const todayAtSeven = new Date();
|
||||
todayAtSeven.setHours(19, 30, 0, 0);
|
||||
|
||||
ctx.args = {timed: todayAtSeven, direction: 'in'};
|
||||
const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||
|
||||
activeCtx.accessToken.userId = salesPersonId;
|
||||
await app.models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id);
|
||||
await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
error = e;
|
||||
await tx.rollback();
|
||||
}
|
||||
|
||||
expect(error).toBeDefined();
|
||||
|
@ -115,49 +108,84 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
|||
|
||||
it('should delete the created time entry for the team boss as himself', async() => {
|
||||
activeCtx.accessToken.userId = teamBossId;
|
||||
const workerId = teamBossId;
|
||||
|
||||
let todayAtFive = new Date();
|
||||
todayAtFive.setHours(17, 30, 0, 0);
|
||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
let data = {
|
||||
workerFk: teamBossId,
|
||||
timed: todayAtFive
|
||||
};
|
||||
const todayAtFive = new Date();
|
||||
todayAtFive.setHours(17, 30, 0, 0);
|
||||
|
||||
timeEntry = await app.models.WorkerTimeControl.addTimeEntry(ctx, data);
|
||||
ctx.args = {timed: todayAtFive, direction: 'in'};
|
||||
const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||
|
||||
createdTimeEntry = await app.models.WorkerTimeControl.findById(timeEntry.id);
|
||||
expect(createdTimeEntry.id).toBeDefined();
|
||||
|
||||
expect(createdTimeEntry).toBeDefined();
|
||||
await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options);
|
||||
|
||||
await app.models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id);
|
||||
const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options);
|
||||
|
||||
createdTimeEntry = await app.models.WorkerTimeControl.findById(timeEntry.id);
|
||||
|
||||
expect(createdTimeEntry).toBeNull();
|
||||
expect(deletedTimeEntry).toBeNull();
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should delete the created time entry for the team boss as HHRR', async() => {
|
||||
activeCtx.accessToken.userId = HHRRId;
|
||||
const workerId = teamBossId;
|
||||
|
||||
let todayAtFive = new Date();
|
||||
todayAtFive.setHours(17, 30, 0, 0);
|
||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
let data = {
|
||||
workerFk: teamBossId,
|
||||
timed: todayAtFive
|
||||
};
|
||||
const todayAtFive = new Date();
|
||||
todayAtFive.setHours(17, 30, 0, 0);
|
||||
|
||||
timeEntry = await app.models.WorkerTimeControl.addTimeEntry(ctx, data);
|
||||
ctx.args = {timed: todayAtFive, direction: 'in'};
|
||||
const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||
|
||||
createdTimeEntry = await app.models.WorkerTimeControl.findById(timeEntry.id);
|
||||
expect(createdTimeEntry.id).toBeDefined();
|
||||
|
||||
expect(createdTimeEntry).toBeDefined();
|
||||
await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options);
|
||||
|
||||
await app.models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id);
|
||||
const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options);
|
||||
|
||||
createdTimeEntry = await app.models.WorkerTimeControl.findById(timeEntry.id);
|
||||
expect(deletedTimeEntry).toBeNull();
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
expect(createdTimeEntry).toBeNull();
|
||||
it('should edit the created time entry for the team boss as HHRR', async() => {
|
||||
activeCtx.accessToken.userId = HHRRId;
|
||||
const workerId = teamBossId;
|
||||
|
||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const todayAtFive = new Date();
|
||||
todayAtFive.setHours(17, 30, 0, 0);
|
||||
|
||||
ctx.args = {timed: todayAtFive, direction: 'in'};
|
||||
const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options);
|
||||
|
||||
expect(createdTimeEntry.id).toBeDefined();
|
||||
|
||||
ctx.args = {direction: 'out'};
|
||||
const updatedTimeEntry = await models.WorkerTimeControl.updateTimeEntry(ctx, createdTimeEntry.id, options);
|
||||
|
||||
expect(updatedTimeEntry.direction).toEqual('out');
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('updateTimeEntry', {
|
||||
description: 'Updates a time entry for a worker if the user role is above the worker',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'The time entry id',
|
||||
http: {source: 'path'}
|
||||
},
|
||||
{
|
||||
arg: 'direction',
|
||||
type: 'string',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
type: 'boolean',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/updateTimeEntry`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.updateTimeEntry = async(ctx, id, options) => {
|
||||
const currentUserId = ctx.req.accessToken.userId;
|
||||
const models = Self.app.models;
|
||||
const args = ctx.args;
|
||||
|
||||
let myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const targetTimeEntry = await Self.findById(id, null, myOptions);
|
||||
const isSubordinate = await models.Worker.isSubordinate(ctx, targetTimeEntry.userFk, myOptions);
|
||||
const isTeamBoss = await models.Account.hasRole(currentUserId, 'teamBoss', myOptions);
|
||||
const isHimself = currentUserId == targetTimeEntry.userFk;
|
||||
|
||||
const notAllowed = isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss);
|
||||
|
||||
if (notAllowed)
|
||||
throw new UserError(`You don't have enough privileges`);
|
||||
|
||||
return targetTimeEntry.updateAttributes({
|
||||
direction: args.direction
|
||||
}, myOptions);
|
||||
};
|
||||
};
|
|
@ -4,6 +4,7 @@ module.exports = Self => {
|
|||
require('../methods/worker-time-control/filter')(Self);
|
||||
require('../methods/worker-time-control/addTimeEntry')(Self);
|
||||
require('../methods/worker-time-control/deleteTimeEntry')(Self);
|
||||
require('../methods/worker-time-control/updateTimeEntry')(Self);
|
||||
|
||||
Self.rewriteDbError(function(err) {
|
||||
if (err.code === 'ER_DUP_ENTRY')
|
||||
|
|
|
@ -9,16 +9,16 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "Number"
|
||||
"type": "number"
|
||||
},
|
||||
"timed": {
|
||||
"type": "Date"
|
||||
"type": "date"
|
||||
},
|
||||
"manual": {
|
||||
"type": "Boolean"
|
||||
"type": "boolean"
|
||||
},
|
||||
"order": {
|
||||
"type": "Number"
|
||||
"type": "number"
|
||||
},
|
||||
"direction": {
|
||||
"type": "string"
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<vn-side-menu side="right">
|
||||
<div class="vn-pa-md">
|
||||
<div class="totalBox vn-mb-sm" style="text-align: center;">
|
||||
<h6>{{'Contract' | translate}} ID: {{$ctrl.businessId}}</h6>
|
||||
<h6>{{'Contract' | translate}} #{{$ctrl.businessId}}</h6>
|
||||
<div>
|
||||
{{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed}}
|
||||
{{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}}
|
||||
|
@ -55,7 +55,7 @@
|
|||
order="businessFk DESC"
|
||||
limit="5">
|
||||
<tpl-item>
|
||||
<div>ID: {{businessFk}}</div>
|
||||
<div>#{{businessFk}}</div>
|
||||
<div class="text-caption text-secondary">
|
||||
{{started | date: 'dd/MM/yyyy'}} - {{ended ? (ended | date: 'dd/MM/yyyy') : 'Indef.'}}
|
||||
</div>
|
||||
|
|
|
@ -43,9 +43,16 @@
|
|||
ng-class="::{'invisible': hour.direction == 'middle'}">
|
||||
</vn-icon>
|
||||
<vn-chip
|
||||
ng-class="::{'colored': hour.manual}"
|
||||
ng-class="::{'colored': hour.manual, 'clickable': true}"
|
||||
removable="::hour.manual"
|
||||
on-remove="$ctrl.showDeleteDialog(hour)">
|
||||
on-remove="$ctrl.showDeleteDialog($event, hour)"
|
||||
ng-click="$ctrl.edit($event, hour)"
|
||||
>
|
||||
<prepend>
|
||||
<vn-icon icon="edit"
|
||||
vn-tooltip="Edit">
|
||||
</vn-icon>
|
||||
</prepend>
|
||||
{{::hour.timed | date: 'HH:mm'}}
|
||||
</vn-chip>
|
||||
</section>
|
||||
|
@ -97,10 +104,20 @@
|
|||
<tpl-body>
|
||||
<vn-input-time
|
||||
vn-one
|
||||
ng-model="$ctrl.newTime"
|
||||
vn-focus
|
||||
ng-model="$ctrl.newTimeEntry.timed"
|
||||
label="Hour"
|
||||
vn-focus>
|
||||
required="true">
|
||||
</vn-input-time>
|
||||
<vn-autocomplete
|
||||
label="Type"
|
||||
ng-model="$ctrl.newTimeEntry.direction"
|
||||
data="$ctrl.entryDirections"
|
||||
select-fields="['code','description']"
|
||||
show-field="description"
|
||||
value-field="code"
|
||||
required="true">
|
||||
</vn-autocomplete>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
|
@ -112,4 +129,22 @@
|
|||
on-accept="$ctrl.deleteTimeEntry()"
|
||||
message="This time entry will be deleted"
|
||||
question="Are you sure you want to delete this entry?">
|
||||
</vn-confirm>
|
||||
</vn-confirm>
|
||||
|
||||
<!-- Edit entry Popover -->
|
||||
<vn-popover vn-id="editEntry">
|
||||
<vn-horizontal class="vn-pa-sm edit-time-entry">
|
||||
<vn-autocomplete class="dense"
|
||||
ng-model="$ctrl.selectedRow.direction"
|
||||
data="$ctrl.entryDirections"
|
||||
select-fields="['code','description']"
|
||||
show-field="description"
|
||||
value-field="code">
|
||||
</vn-autocomplete>
|
||||
<vn-icon-button vn-none
|
||||
icon="check"
|
||||
vn-tooltip="Save"
|
||||
ng-click="$ctrl.save()">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
</vn-popover>
|
|
@ -7,6 +7,11 @@ class Controller extends Section {
|
|||
super($element, $);
|
||||
this.weekDays = [];
|
||||
this.weekdayNames = vnWeekDays.locales;
|
||||
this.entryDirections = [
|
||||
{code: 'in', description: this.$t('In')},
|
||||
{code: 'middle', description: this.$t('Intermediate')},
|
||||
{code: 'out', description: this.$t('Out')}
|
||||
];
|
||||
}
|
||||
|
||||
$postLink() {
|
||||
|
@ -241,21 +246,34 @@ class Controller extends Section {
|
|||
const timed = new Date(weekday.dated.getTime());
|
||||
timed.setHours(0, 0, 0, 0);
|
||||
|
||||
this.newTime = timed;
|
||||
this.newTimeEntry = {
|
||||
workerFk: this.$params.id,
|
||||
timed: timed
|
||||
};
|
||||
this.selectedWeekday = weekday;
|
||||
this.$.addTimeDialog.show();
|
||||
}
|
||||
|
||||
addTime() {
|
||||
let data = {
|
||||
workerFk: this.$params.id,
|
||||
timed: this.newTime
|
||||
};
|
||||
this.$http.post(`WorkerTimeControls/addTimeEntry`, data)
|
||||
.then(() => this.fetchHours());
|
||||
try {
|
||||
const entry = this.newTimeEntry;
|
||||
if (!entry.direction)
|
||||
throw new Error(`The entry type can't be empty`);
|
||||
|
||||
const query = `WorkerTimeControls/${this.worker.id}/addTimeEntry`;
|
||||
this.$http.post(query, entry)
|
||||
.then(() => this.fetchHours());
|
||||
} catch (e) {
|
||||
this.vnApp.showError(this.$t(e.message));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
showDeleteDialog(hour) {
|
||||
showDeleteDialog($event, hour) {
|
||||
$event.preventDefault();
|
||||
|
||||
this.timeEntryToDelete = hour;
|
||||
this.$.deleteEntryDialog.show();
|
||||
}
|
||||
|
@ -268,6 +286,29 @@ class Controller extends Section {
|
|||
this.vnApp.showSuccess(this.$t('Entry removed'));
|
||||
});
|
||||
}
|
||||
|
||||
edit($event, hour) {
|
||||
if ($event.defaultPrevented) return;
|
||||
|
||||
this.selectedRow = hour;
|
||||
this.$.editEntry.show($event);
|
||||
}
|
||||
|
||||
save() {
|
||||
try {
|
||||
const entry = this.selectedRow;
|
||||
if (!entry.direction)
|
||||
throw new Error(`The entry type can't be empty`);
|
||||
|
||||
const query = `WorkerTimeControls/${entry.id}/updateTimeEntry`;
|
||||
this.$http.post(query, {direction: entry.direction})
|
||||
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')))
|
||||
.then(() => this.$.editEntry.hide())
|
||||
.then(() => this.fetchHours());
|
||||
} catch (e) {
|
||||
this.vnApp.showError(this.$t(e.message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
|
||||
|
|
|
@ -113,5 +113,21 @@ describe('Component vnWorkerTimeControl', () => {
|
|||
expect(result).toEqual('01:00');
|
||||
});
|
||||
});
|
||||
|
||||
describe('save() ', () => {
|
||||
it(`should make a query an then call to the fetchHours() method`, () => {
|
||||
controller.fetchHours = jest.fn();
|
||||
controller.selectedRow = {id: 1, timed: new Date(), direction: 'in'};
|
||||
controller.$.editEntry = {
|
||||
hide: () => {}
|
||||
};
|
||||
const expectedParams = {direction: 'in'};
|
||||
$httpBackend.expect('POST', 'WorkerTimeControls/1/updateTimeEntry', expectedParams).respond(200);
|
||||
controller.save();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.fetchHours).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
In: Entrada
|
||||
Out: Salida
|
||||
Intermediate: Intermedio
|
||||
Hour: Hora
|
||||
Hours: Horas
|
||||
Add time: Añadir hora
|
||||
|
@ -8,4 +9,5 @@ Current week: Semana actual
|
|||
This time entry will be deleted: Se eliminará la hora fichada
|
||||
Are you sure you want to delete this entry?: ¿Seguro que quieres eliminarla?
|
||||
Finish at: Termina a las
|
||||
Entry removed: Fichada borrada
|
||||
Entry removed: Fichada borrada
|
||||
The entry type can't be empty: El tipo de fichada no puede quedar vacía
|
|
@ -24,4 +24,8 @@ vn-worker-time-control {
|
|||
.totalBox {
|
||||
max-width: none
|
||||
}
|
||||
}
|
||||
|
||||
.edit-time-entry {
|
||||
width: 200px
|
||||
}
|
Loading…
Reference in New Issue