diff --git a/back/models/warehouse.json b/back/models/warehouse.json index eb86e2114..dcbf7f2d2 100644 --- a/back/models/warehouse.json +++ b/back/models/warehouse.json @@ -24,9 +24,6 @@ }, "isManaged":{ "type": "boolean" - }, - "hasStowaway":{ - "type": "boolean" } }, "acls": [ diff --git a/db/changes/10480-june/00-item.sql b/db/changes/10480-june/00-item.sql new file mode 100644 index 000000000..a08d3f4c1 --- /dev/null +++ b/db/changes/10480-june/00-item.sql @@ -0,0 +1 @@ +ALTER TABLE `vn`.`item` MODIFY COLUMN description TEXT CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT NULL NULL; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index cee45c3df..5a2188cb5 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -139,14 +139,14 @@ INSERT INTO `vn`.`warehouseAlias`(`id`, `name`) (1, 'Main Warehouse'), (2, 'Gotham'); -INSERT INTO `vn`.`warehouse`(`id`, `name`, `code`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`, `hasDms`, `hasComission`, `aliasFk`, `countryFk`, `hasProduction`) +INSERT INTO `vn`.`warehouse`(`id`, `name`, `code`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasDms`, `hasComission`, `aliasFk`, `countryFk`, `hasProduction`) VALUES - (1, 'Warehouse One', 'ALG', 1, 1, 1, 1, 1, 1, 1, 2, 1, 1), - (2, 'Warehouse Two', NULL, 1, 1, 1, 1, 0, 0, 1, 2, 13, 1), - (3, 'Warehouse Three', NULL, 1, 1, 1, 1, 0, 0, 0, 2, 1, 1), - (4, 'Warehouse Four', NULL, 1, 1, 1, 1, 0, 0, 0, 2, 1, 1), - (5, 'Warehouse Five', NULL, 1, 1, 1, 1, 0, 0, 0, 2, 1, 1), - (13, 'Inventory', NULL, 1, 1, 1, 0, 0, 0, 0, 2, 1, 0); + (1, 'Warehouse One', 'ALG', 1, 1, 1, 1, 1, 1, 2, 1, 1), + (2, 'Warehouse Two', NULL, 1, 1, 1, 1, 0, 1, 2, 13, 1), + (3, 'Warehouse Three', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1), + (4, 'Warehouse Four', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1), + (5, 'Warehouse Five', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1), + (13, 'Inventory', NULL, 1, 1, 1, 0, 0, 0, 2, 1, 0); INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPreparedByPacking`, `code`) VALUES @@ -698,10 +698,6 @@ INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `workerFk`, `created`) (23, 16, 21, util.VN_NOW()), (24, 16, 21, util.VN_NOW()); -INSERT INTO `vn`.`stowaway`(`id`, `shipFk`, `created`) - VALUES - (12, 13, util.VN_CURDATE()); - INSERT INTO `vn`.`deliveryPoint` (`id`, `name`, `ubication`) VALUES (1, 'Gotham','1007 Mountain Drive, Gotham'); @@ -1967,7 +1963,8 @@ INSERT INTO `postgresql`.`calendar_employee` (`business_id`, `calendar_state_id` (1107, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, DATE_ADD(util.VN_CURDATE(), INTERVAL -20 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 20 DAY))), (1107, 2, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, DATE_ADD(util.VN_CURDATE(), INTERVAL -13 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 8 DAY))), (1107, 1, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, DATE_ADD(util.VN_CURDATE(), INTERVAL -14 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 9 DAY))), - (1107, 2, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, DATE_ADD(util.VN_CURDATE(), INTERVAL -15 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 7 DAY))); + (1107, 2, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, DATE_ADD(util.VN_CURDATE(), INTERVAL -15 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 7 DAY))), + (1107, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL - 16 DAY)); INSERT INTO `vn`.`smsConfig` (`id`, `uri`, `title`, `apiKey`) VALUES @@ -2237,8 +2234,8 @@ INSERT INTO `vn`.`workerTimeControl`(`userFk`, `timed`, `manual`, `direction`) VALUES (1106, CONCAT(util.VN_CURDATE(), ' 07:00'), TRUE, 'in'), (1106, CONCAT(util.VN_CURDATE(), ' 10:00'), TRUE, 'middle'), - (1106, CONCAT(util.VN_CURDATE(), ' 10:10'), TRUE, 'middle'), - (1106, CONCAT(util.VN_CURDATE(), ' 15:00'), TRUE, 'out'); + (1106, CONCAT(util.VN_CURDATE(), ' 10:20'), TRUE, 'middle'), + (1106, CONCAT(util.VN_CURDATE(), ' 14:50'), TRUE, 'out'); INSERT INTO `vn`.`dmsType`(`id`, `name`, `path`, `readRoleFk`, `writeRoleFk`, `code`) VALUES @@ -2606,3 +2603,7 @@ INSERT INTO `vn`.`sectorCollection` (`userFk`, `sectorFk`) INSERT INTO `vn`.`sectorCollectionSaleGroup` (`sectorCollectionFk`, `saleGroupFk`) VALUES (1, 1); + +INSERT INTO `vn`.`workerTimeControlConfig` (`id`, `dayBreak`, `dayBreakDriver`, `shortWeekBreak`, `longWeekBreak`, `weekScope`, `mailPass`, `mailHost`, `mailSuccessFolder`, `mailErrorFolder`, `mailUser`, `minHoursToBreak`, `breakHours`, `hoursCompleteWeek`, `startNightlyHours`, `endNightlyHours`, `maxTimePerDay`, `breakTime`, `timeToBreakTime`, `dayMaxTime`, `shortWeekDays`, `longWeekDays`) + VALUES + (1, 43200, 32400, 129600, 259200, 604800, '', '', 'Leidos.exito', 'Leidos.error', 'timeControl', 5.33, 0.33, 40, '22:00:00', '06:00:00', 57600, 1200, 18000, 57600, 6, 13); \ No newline at end of file diff --git a/db/dump/structure.sql b/db/dump/structure.sql index 24333ff64..2c0e8231a 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -44093,6 +44093,7 @@ WHERE RETURN vPhyto; END ;; DELIMITER ; + /*!50003 SET sql_mode = @saved_sql_mode */ ; /*!50003 SET character_set_client = @saved_cs_client */ ; /*!50003 SET character_set_results = @saved_cs_results */ ; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index cbcf11746..e939838cb 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -565,8 +565,6 @@ export default { isDeletedIcon: 'vn-ticket-descriptor vn-icon[icon="icon-deletedTicket"]', goBackToModuleIndexButton: 'vn-ticket-descriptor a[ui-sref="ticket.index"]', moreMenu: 'vn-ticket-descriptor vn-ticket-descriptor-menu > vn-icon-button[icon=more_vert]', - moreMenuAddStowaway: '.vn-menu [name="addStowaway"]', - moreMenuDeleteStowawayButton: '.vn-menu [name="deleteStowaway"]', moreMenuAddToTurn: '.vn-menu [name="addTurn"]', moreMenuDeleteTicket: '.vn-menu [name="deleteTicket"]', moreMenuRestoreTicket: '.vn-menu [name="restoreTicket"]', @@ -579,8 +577,6 @@ export default { sendSMSbutton: 'button[response="accept"]', changeShippedHourDialog: '.vn-dialog.shown', changeShippedHour: '.vn-dialog.shown vn-input-time[ng-model="$ctrl.newShipped"]', - addStowawayDialogFirstTicket: '.vn-dialog.shown vn-table vn-tbody vn-tr', - shipButton: 'vn-ticket-descriptor vn-icon[icon="icon-stowaway"]', thursdayButton: '.vn-popup.shown vn-tool-bar > vn-button:nth-child(4)', saturdayButton: '.vn-popup.shown vn-tool-bar > vn-button:nth-child(6)', acceptDialog: '.vn-dialog.shown button[response="accept"]', @@ -588,7 +584,6 @@ export default { descriptorDeliveryDate: 'vn-ticket-descriptor slot-body > .attributes > vn-label-value:nth-child(4) > section > span', descriptorDeliveryAgency: 'vn-ticket-descriptor slot-body > .attributes > vn-label-value:nth-child(5) > section > span', acceptInvoiceOutButton: '.vn-confirm.shown button[response="accept"]', - acceptDeleteStowawayButton: '.vn-dialog.shown button[response="accept"]' }, ticketNotes: { firstNoteRemoveButton: 'vn-icon[icon="delete"]', @@ -911,52 +906,16 @@ export default { 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', - thursdayAddTimeButton: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-icon-button', - 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: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)', + firstEntryOfMondayDelete: 'vn-worker-time-control vn-table > div > vn-tbody > vn-tr > vn-td:nth-child(1) > section:nth-child(1) > vn-chip > vn-icon[icon="cancel"]', 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: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)', - thursdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(4)', - fridayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(5)', - saturdayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(6)', - sundayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(7)', weekWorkedHours: 'vn-worker-time-control vn-side-menu vn-label-value > section > span', nextMonthButton: 'vn-worker-time-control vn-side-menu vn-calendar vn-button[icon=keyboard_arrow_right]', previousMonthButton: 'vn-worker-time-control vn-side-menu vn-calendar vn-button[icon=keyboard_arrow_left]', + monthName: 'vn-worker-time-control vn-side-menu vn-calendar div > .title', secondWeekDay: 'vn-worker-time-control vn-side-menu vn-calendar .day:nth-child(8) > .day-number', + thrirdWeekDay: 'vn-worker-time-control vn-side-menu vn-calendar .day:nth-child(15) > .day-number', navigateBackToIndex: 'vn-worker-descriptor [name="goToModuleIndex"]' }, workerCalendar: { diff --git a/e2e/paths/02-client/05_add_address.spec.js b/e2e/paths/02-client/05_add_address.spec.js index c35237ab4..0581635d0 100644 --- a/e2e/paths/02-client/05_add_address.spec.js +++ b/e2e/paths/02-client/05_add_address.spec.js @@ -45,7 +45,7 @@ describe('Client Add address path', () => { expect(province).toContain('Province five'); }); - it(`should receive an error after clicking save button as consignee, incoterms and customsAgent are empty`, async() => { + it(`should throw after clicking save button as consignee, incoterms and customsAgent are empty`, async() => { await page.write(selectors.clientAddresses.consignee, 'Bruce Bunner'); await page.write(selectors.clientAddresses.streetAddress, '320 Park Avenue New York'); await page.waitToClick(selectors.clientAddresses.saveButton); diff --git a/e2e/paths/03-worker/04_time_control.spec.js b/e2e/paths/03-worker/04_time_control.spec.js index 5709e6207..be8df3cf0 100644 --- a/e2e/paths/03-worker/04_time_control.spec.js +++ b/e2e/paths/03-worker/04_time_control.spec.js @@ -1,3 +1,4 @@ +/* eslint max-len: ["error", { "code": 150 }]*/ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; @@ -10,414 +11,105 @@ describe('Worker time control path', () => { await page.loginAndModule('salesBoss', 'worker'); await page.accessToSearchResult('HankPym'); await page.accessToSection('worker.card.timeControl'); - await page.waitToClick(selectors.workerTimeControl.previousMonthButton); - await page.waitToClick(selectors.workerTimeControl.secondWeekDay); }); afterAll(async() => { await browser.close(); }); - describe('as salesBoss', () => { - describe('on Monday', () => { - it('should scan in Hank Pym', async() => { - const scanTime = '07:00'; + const eightAm = '08:00'; + const fourPm = '16:00'; + const hankPymId = 1107; - await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); - 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'); + it('should go to the next month', async() => { + const date = new Date(); + date.setMonth(date.getMonth() + 1); + const month = date.toLocaleString('default', {month: 'long'}); - expect(result).toEqual(scanTime); - }); + await page.waitToClick(selectors.workerTimeControl.nextMonthButton); + const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); - it(`should scan out Hank Pym for break`, async() => { - const scanTime = '10:00'; - - await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - it(`should scan in Hank Pym for a wrong hour and forget to scan in from the break`, async() => { - const scanTime = '18:00'; - - await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - it(`should delete the wrong entry for Hank Pym`, async() => { - const wrongScanTime = '18:00'; - - await page.waitForTextInElement(selectors.workerTimeControl.thirdEntryOfMonday, wrongScanTime); - await page.waitToClick(selectors.workerTimeControl.thirdEntryOfMondayDelete); - await page.respondToDialog('accept'); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Entry removed'); - }); - - it(`should scan out Hank Pym to leave early`, async() => { - const scanTime = '14:00'; - - await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - it(`should add the break's scan in for Hank Pym and be in the right order`, async() => { - const scanTime = '10:20'; - - await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); - 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'); - - expect(result).toEqual('14:00'); - }); - - it(`should the third entry be the scan in from break`, async() => { - const scanTime = '10:20'; - - const result = await page - .waitToGetProperty(selectors.workerTimeControl.thirdEntryOfMonday, 'innerText'); - - expect(result).toEqual(scanTime); - }); - - it(`should check Hank Pym worked 6:40 hours`, async() => { - await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '06:40 h.'); - }); - }); - - describe('on Tuesday', () => { - it('should happily scan in Hank Pym', async() => { - const scanTime = '08:00'; - - await page.waitToClick(selectors.workerTimeControl.tuesdayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - it(`should happily scan out Hank Pym for break`, async() => { - const scanTime = '10:00'; - - await page.waitToClick(selectors.workerTimeControl.tuesdayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - it(`should happily scan in Hank Pym from the break`, async() => { - const scanTime = '10:20'; - - await page.waitToClick(selectors.workerTimeControl.tuesdayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - it(`should happily scan out Hank Pym for the day`, async() => { - const scanTime = '16:00'; - - await page.waitToClick(selectors.workerTimeControl.tuesdayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - it(`should check Hank Pym worked 7:40 hours`, async() => { - await page.waitForTextInElement(selectors.workerTimeControl.tuesdayWorkedHours, '07:40 h.'); - }); - }); - - describe('on Wednesday', () => { - it('should cheerfully scan in Hank Pym', async() => { - const scanTime = '09:00'; - - await page.waitToClick(selectors.workerTimeControl.wednesdayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - it(`should cheerfully scan out Hank Pym for break`, async() => { - const scanTime = '10:00'; - - await page.waitToClick(selectors.workerTimeControl.wednesdayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - it(`should cheerfully scan in Hank Pym from the break`, async() => { - const scanTime = '10:20'; - - await page.waitToClick(selectors.workerTimeControl.wednesdayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - it(`should cheerfully scan out Hank Pym for the day`, async() => { - const scanTime = '17:00'; - - await page.waitToClick(selectors.workerTimeControl.wednesdayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - it(`should check Hank Pym worked 7:40 cheerfull hours`, async() => { - await page.waitForTextInElement(selectors.workerTimeControl.wednesdayWorkedHours, '07:40 h.'); - }); - }); - - describe('on Thursday', () => { - it('should joyfully scan in Hank Pym', async() => { - const scanTime = '09:59'; - - await page.waitToClick(selectors.workerTimeControl.thursdayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - 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.dialogTimeInput, scanTime); - await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate'); - await page.respondToDialog('accept'); - const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfThursday, 'innerText'); - - expect(result).toEqual(scanTime); - }); - - 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.dialogTimeInput, scanTime); - await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate'); - await page.respondToDialog('accept'); - const result = await page.waitToGetProperty(selectors.workerTimeControl.thirdEntryOfThursday, 'innerText'); - - expect(result).toEqual(scanTime); - }); - - 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.dialogTimeInput, scanTime); - await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); - await page.respondToDialog('accept'); - const result = await page.waitToGetProperty(selectors.workerTimeControl.fourthEntryOfThursday, 'innerText'); - - expect(result).toEqual(scanTime); - }); - - it(`should check Hank Pym worked 7:40 joyfull hours`, async() => { - await page.waitForTextInElement(selectors.workerTimeControl.thursdayWorkedHours, '07:40 h.'); - }); - }); - - describe('on Friday', () => { - it('should smilingly scan in Hank Pym', async() => { - const scanTime = '07:30'; - await page.waitToClick(selectors.workerTimeControl.fridayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - 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.dialogTimeInput, scanTime); - await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate'); - await page.respondToDialog('accept'); - const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfFriday, 'innerText'); - - expect(result).toEqual(scanTime); - }); - - 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.dialogTimeInput, scanTime); - await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'intermediate'); - await page.respondToDialog('accept'); - const result = await page.waitToGetProperty(selectors.workerTimeControl.thirdEntryOfFriday, 'innerText'); - - expect(result).toEqual(scanTime); - }); - - 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.dialogTimeInput, scanTime); - await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); - await page.respondToDialog('accept'); - const result = await page.waitToGetProperty(selectors.workerTimeControl.fourthEntryOfFriday, 'innerText'); - - expect(result).toEqual(scanTime); - }); - - it(`should check Hank Pym worked 7:40 hours with a smile on his face`, async() => { - await page.waitForTextInElement(selectors.workerTimeControl.fridayWorkedHours, '07:40 h.'); - }); - }); + expect(result).toContain(month); }); - describe('as HHRR', () => { - describe('on Saturday', () => { - it('should log in as hr and pick the worker module', async() => { - await page.loginAndModule('hr', 'worker'); - }); + it('should go to current month', async() => { + const date = new Date(); + const month = date.toLocaleString('default', {month: 'long'}); - it('should search for a worker and access to its summary', async() => { - await page.accessToSearchResult('HankPym'); - await page.waitForState('worker.card.summary'); - }); + await page.waitToClick(selectors.workerTimeControl.previousMonthButton); + const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); - it('should access to the time control section', async() => { - await page.accessToSection('worker.card.timeControl'); - await page.waitForState('worker.card.timeControl'); - await page.waitToClick(selectors.workerTimeControl.previousMonthButton); - await page.waitToClick(selectors.workerTimeControl.secondWeekDay); - }); - - 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.dialogTimeInput, scanTime); - await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in'); - await page.respondToDialog('accept'); - const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfSaturday, 'innerText'); - - expect(result).toEqual(scanTime); - }); - - 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.dialogTimeInput, scanTime); - await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); - await page.respondToDialog('accept'); - const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfSaturday, 'innerText'); - - expect(result).toEqual(scanTime); - }); - - it(`should check Hank Pym worked 7:40 hours with all his will`, async() => { - await page.waitForTextInElement(selectors.workerTimeControl.saturdayWorkedHours, '07:40 h.'); - }); - }); - - describe('on Sunday', () => { - it('should gladly scan in Hank Pym', async() => { - const scanTime = '05:00'; - await page.waitToClick(selectors.workerTimeControl.sundayAddTimeButton); - 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'); - - expect(result).toEqual(scanTime); - }); - - 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.dialogTimeInput, scanTime); - await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); - await page.respondToDialog('accept'); - const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfSunday, 'innerText'); - - expect(result).toEqual(scanTime); - }); - - it(`should check Hank Pym worked 7:40 glad hours`, async() => { - await page.waitForTextInElement(selectors.workerTimeControl.sundayWorkedHours, '07:40 h.'); - }); - - it(`should check Hank Pym doesn't have hours set on the next months second week`, async() => { - await page.waitToClick(selectors.workerTimeControl.nextMonthButton); - await page.waitToClick(selectors.workerTimeControl.secondWeekDay); - await page.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '00:00 h.'); - }); - - it(`should check he didn't scan in this week yet`, async() => { - await page.waitToClick(selectors.workerTimeControl.navigateBackToIndex); - await page.accessToSearchResult('salesBoss'); - await page.accessToSection('worker.card.timeControl'); - - const wholeWeekHours = await page - .waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText'); - - expect(wholeWeekHours).toEqual('00:00 h.'); - }); - }); + expect(result).toContain(month); }); - describe('after all this amazing week', () => { - it('should log in Hank', async() => { - await page.loginAndModule('HankPym', 'worker'); - await page.accessToSearchResult('HankPym'); - await page.accessToSection('worker.card.timeControl'); - await page.waitToClick(selectors.workerTimeControl.previousMonthButton); - await page.waitToClick(selectors.workerTimeControl.secondWeekDay); - }); + it('should go 1 month in the past', async() => { + const date = new Date(); + date.setMonth(date.getMonth() - 1); + const timestamp = Math.round(date.getTime() / 1000); + const month = date.toLocaleString('default', {month: 'long'}); - it('should check his weekly hours are alright', async() => { - await page.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '52:40 h.'); - }); + await page.loginAndModule('salesBoss', 'worker'); + await page.goto(`http://localhost:5000/#!/worker/${hankPymId}/time-control?timestamp=${timestamp}`); + await page.waitToClick(selectors.workerTimeControl.secondWeekDay); + + const result = await page.waitToGetProperty(selectors.workerTimeControl.monthName, 'innerText'); + + expect(result).toContain(month); + }); + + it(`should return error when insert 'out' of first entry`, async() => { + await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); + await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm); + await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); + await page.respondToDialog('accept'); + const message = await page.waitForSnackbar(); + + expect(message.text).toBeDefined(); + }); + + it(`should insert 'in' monday`, async() => { + await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); + await page.pickTime(selectors.workerTimeControl.dialogTimeInput, eightAm); + await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'in'); + await page.respondToDialog('accept'); + const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText'); + + expect(result).toEqual(eightAm); + }); + + it(`should insert 'out' monday`, async() => { + await page.waitToClick(selectors.workerTimeControl.mondayAddTimeButton); + await page.pickTime(selectors.workerTimeControl.dialogTimeInput, fourPm); + await page.autocompleteSearch(selectors.workerTimeControl.dialogTimeDirection, 'out'); + await page.respondToDialog('accept'); + const result = await page.waitToGetProperty(selectors.workerTimeControl.secondEntryOfMonday, 'innerText'); + + expect(result).toEqual(fourPm); + }); + + it(`should check Hank Pym worked 8:20 hours`, async() => { + await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '08:20 h.'); + await page.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '08:20 h.'); + }); + + it('should remove first entry of monday', async() => { + await page.waitForTextInElement(selectors.workerTimeControl.firstEntryOfMonday, eightAm); + await page.waitForTextInElement(selectors.workerTimeControl.secondEntryOfMonday, fourPm); + await page.waitToClick(selectors.workerTimeControl.firstEntryOfMondayDelete); + await page.respondToDialog('accept'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Entry removed'); + }); + + it(`should be the 'out' the first entry of monday`, async() => { + const result = await page.waitToGetProperty(selectors.workerTimeControl.firstEntryOfMonday, 'innerText'); + + expect(result).toEqual(fourPm); + }); + + it('should change week of month', async() => { + await page.waitToClick(selectors.workerTimeControl.thrirdWeekDay); + await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '00:00 h.'); }); }); diff --git a/e2e/paths/05-ticket/12_descriptor.spec.js b/e2e/paths/05-ticket/12_descriptor.spec.js index 3429acc89..ca6fb8290 100644 --- a/e2e/paths/05-ticket/12_descriptor.spec.js +++ b/e2e/paths/05-ticket/12_descriptor.spec.js @@ -75,59 +75,6 @@ describe('Ticket descriptor path', () => { }); }); - describe('Add stowaway', () => { - it('should search for a ticket', async() => { - await page.accessToSearchResult('16'); - await page.waitForState('ticket.card.summary'); - }); - - it('should open the add stowaway dialog', async() => { - await page.waitForFunction(() => { - let element = document.querySelector('vn-ticket-descriptor-menu'); - return element.$ctrl.canShowStowaway === true; - }); - await page.waitToClick(selectors.ticketDescriptor.moreMenu); - await page.waitToClick(selectors.ticketDescriptor.moreMenuAddStowaway); - await page.waitForSelector(selectors.ticketDescriptor.addStowawayDialogFirstTicket); - const isVisible = await page.isVisible(selectors.ticketDescriptor.addStowawayDialogFirstTicket); - - expect(isVisible).toBeTruthy(); - }); - - it('should add a ticket as stowaway', async() => { - await page.waitToClick(selectors.ticketDescriptor.addStowawayDialogFirstTicket); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Data saved!'); - }); - - it(`should check the state of the stowaway ticket is embarked`, async() => { - await page.waitForState('ticket.card.summary'); - const state = await page.waitToGetProperty(selectors.ticketDescriptor.stateLabelValue, 'innerText'); - - expect(state).toEqual('State Embarcando'); - }); - - it(`should navigate back to the added ticket using the descriptors ship button`, async() => { - await page.waitToClick(selectors.ticketDescriptor.shipButton); - await page.waitForState('ticket.card.summary'); - }); - - it('should delete the stowaway', async() => { - await page.waitToClick(selectors.ticketDescriptor.moreMenu); - await page.waitForContentLoaded(); - await page.waitToClick(selectors.ticketDescriptor.moreMenuDeleteStowawayButton); - await page.waitToClick(selectors.ticketDescriptor.acceptDeleteStowawayButton); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Data saved!'); - }); - - it(`should confirm the ship buton doesn't exisist any more`, async() => { - await page.waitForSelector(selectors.ticketDescriptor.shipButton, {hidden: true}); - }); - }); - describe('Make invoice', () => { it('should login as administrative role then search for a ticket', async() => { const invoiceableTicketId = '14'; diff --git a/e2e/paths/05-ticket/14_create_ticket.spec.js b/e2e/paths/05-ticket/14_create_ticket.spec.js index d72557f99..48b4ebdd0 100644 --- a/e2e/paths/05-ticket/14_create_ticket.spec.js +++ b/e2e/paths/05-ticket/14_create_ticket.spec.js @@ -6,7 +6,6 @@ describe('Ticket create path', () => { let page; let nextMonth = new Date(); nextMonth.setMonth(nextMonth.getMonth() + 1); - let stowawayTicketId; beforeAll(async() => { browser = await getBrowser(); @@ -36,8 +35,6 @@ describe('Ticket create path', () => { it('should check the url is now the summary of the ticket', async() => { await page.waitForState('ticket.card.summary'); - stowawayTicketId = await page.waitToGetProperty(selectors.ticketSummary.descriptorTicketId, 'innerText'); - stowawayTicketId = stowawayTicketId.substring(1); }); it('should again open the new ticket form', async() => { @@ -61,15 +58,6 @@ describe('Ticket create path', () => { await page.waitForState('ticket.card.summary'); }); - it('should make the previously created ticket the stowaway of the current ticket', async() => { - await page.waitToClick(selectors.ticketDescriptor.moreMenu); - await page.waitToClick(selectors.ticketDescriptor.moreMenuAddStowaway); - await page.waitToClick(selectors.ticketDescriptor.addStowawayDialogFirstTicket); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain('Data saved!'); - }); - it('should delete the current ticket', async() => { await page.waitToClick(selectors.ticketDescriptor.moreMenu); await page.waitToClick(selectors.ticketDescriptor.moreMenuDeleteTicket); @@ -78,11 +66,4 @@ describe('Ticket create path', () => { expect(message.text).toContain('Ticket deleted. You can undo this action within the first hour'); }); - - it('should search for the stowaway ticket of the previously deleted ticket', async() => { - await page.accessToSearchResult(stowawayTicketId); - const result = await page.countElement(selectors.ticketDescriptor.shipButton); - - expect(result).toBe(0); - }); }); diff --git a/front/core/styles/icons/salixfont.css b/front/core/styles/icons/salixfont.css index c500f976d..2dee94c3b 100644 --- a/front/core/styles/icons/salixfont.css +++ b/front/core/styles/icons/salixfont.css @@ -343,9 +343,6 @@ .icon-splur:before { content: "\e970"; } -.icon-stowaway:before { - content: "\e94f"; -} .icon-supplier:before { content: "\e925"; } diff --git a/front/core/styles/icons/salixfont.svg b/front/core/styles/icons/salixfont.svg index 2b8b1ac8a..96a584734 100644 --- a/front/core/styles/icons/salixfont.svg +++ b/front/core/styles/icons/salixfont.svg @@ -85,8 +85,6 @@ - - diff --git a/loopback/locale/en.json b/loopback/locale/en.json index c9dca734f..ccf16cce0 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -54,7 +54,6 @@ "You can't delete a confirmed order": "You can't delete a confirmed order", "Value has an invalid format": "Value has an invalid format", "The postcode doesn't exist. Please enter a correct one": "The postcode doesn't exist. Please enter a correct one", - "Can't create stowaway for this ticket": "Can't create stowaway for this ticket", "Swift / BIC can't be empty": "Swift / BIC can't be empty", "Deleted sales from ticket": "I have deleted the following lines from the ticket [{{ticketId}}]({{{ticketUrl}}}): {{{deletions}}}", "Added sale to ticket": "I have added the following line to the ticket [{{ticketId}}]({{{ticketUrl}}}): {{{addition}}}", @@ -70,7 +69,6 @@ "Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked", "Claim state has changed to incomplete": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *incomplete*", "Claim state has changed to canceled": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *canceled*", - "This ticket is not an stowaway anymore": "The ticket id [{{ticketId}}]({{{ticketUrl}}}) is not an stowaway anymore", "Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member", "Incoterms is required for a non UEE member": "Incoterms is required for a non UEE member", "Client checked as validated despite of duplication": "Client checked as validated despite of duplication from client id {{clientId}}", @@ -124,5 +122,13 @@ "isWithoutNegatives": "isWithoutNegatives", "routeFk": "routeFk", "Not enough privileges to edit a client with verified data": "Not enough privileges to edit a client with verified data", - "Can't change the password of another worker": "Can't change the password of another worker" + "Can't change the password of another worker": "Can't change the password of another worker", + "No hay un contrato en vigor": "There is no existing contract", + "No está permitido trabajar": "Not allowed to work", + "Dirección incorrecta": "Wrong direction", + "No se permite fichar a futuro": "It is not allowed to sign in the future", + "Descanso diario 12h.": "Daily rest 12h.", + "Fichadas impares": "Odd signs", + "Descanso diario 9h.": "Daily rest 9h.", + "Descanso semanal 36h. / 72h.": "Weekly rest 36h. / 72h." } \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 23c2281c3..38ac2d86c 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -101,7 +101,6 @@ "Ticket id cannot be blank": "El id de ticket no puede quedar en blanco", "Weekday cannot be blank": "El día de la semana no puede quedar en blanco", "You can't delete a confirmed order": "No puedes borrar un pedido confirmado", - "Can't create stowaway for this ticket": "No se puede crear un polizon para este ticket", "The social name has an invalid format": "El nombre fiscal tiene un formato incorrecto", "Invalid quantity": "Cantidad invalida", "This postal code is not valid": "This postal code is not valid", @@ -138,7 +137,6 @@ "Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*", "Claim state has changed to incomplete": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *incompleta*", "Claim state has changed to canceled": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *anulado*", - "This ticket is not an stowaway anymore": "El ticket id [{{ticketId}}]({{{ticketUrl}}}) ha dejado de ser un polizón", "Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}", "ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto", "Distance must be lesser than 1000": "La distancia debe ser inferior a 1000", @@ -227,5 +225,12 @@ "This ticket is already a refund": "Este ticket ya es un abono", "isWithoutNegatives": "isWithoutNegatives", "routeFk": "routeFk", - "Can't change the password of another worker": "No se puede cambiar la contraseña de otro trabajador" + "Can't change the password of another worker": "No se puede cambiar la contraseña de otro trabajador", + "No hay un contrato en vigor": "No hay un contrato en vigor", + "No se permite fichar a futuro": "No se permite fichar a futuro", + "No está permitido trabajar": "No está permitido trabajar", + "Fichadas impares": "Fichadas impares", + "Descanso diario 12h.": "Descanso diario 12h.", + "Descanso semanal 36h. / 72h.": "Descanso semanal 36h. / 72h.", + "Dirección incorrecta": "Dirección incorrecta" } \ No newline at end of file diff --git a/modules/claim/back/methods/claim-beginning/importToNewRefundTicket.js b/modules/claim/back/methods/claim-beginning/importToNewRefundTicket.js index de812417a..22a48f83e 100644 --- a/modules/claim/back/methods/claim-beginning/importToNewRefundTicket.js +++ b/modules/claim/back/methods/claim-beginning/importToNewRefundTicket.js @@ -1,6 +1,6 @@ module.exports = Self => { Self.remoteMethodCtx('importToNewRefundTicket', { - description: 'Imports lines from claimBeginning to a new ticket with specific shipped, landed dates, agency and company', + description: 'Import lines of claimBeginning to new ticket with shipped, landed dates, agency and company', accessType: 'WRITE', accepts: [{ arg: 'id', diff --git a/modules/client/front/extended-list/index.html b/modules/client/front/extended-list/index.html index b45a0bc5f..784e88b8a 100644 --- a/modules/client/front/extended-list/index.html +++ b/modules/client/front/extended-list/index.html @@ -162,7 +162,7 @@ {{::client.province | dashIfEmpty}} {{::client.city | dashIfEmpty}} {{::client.postcode | dashIfEmpty}} - {{::client.email | dashIfEmpty}} + {{::client.email | dashIfEmpty}} {{::client.created | date:'dd/MM/yyyy'}} {{::client.businessType | dashIfEmpty}} {{::client.payMethod | dashIfEmpty}} diff --git a/modules/entry/back/methods/entry/lastItemBuys.js b/modules/entry/back/methods/entry/lastItemBuys.js index 7e83f1e5f..87b99c229 100644 --- a/modules/entry/back/methods/entry/lastItemBuys.js +++ b/modules/entry/back/methods/entry/lastItemBuys.js @@ -63,7 +63,6 @@ module.exports = Self => { stmt = new ParameterizedSQL( `CREATE TEMPORARY TABLE tmp.item (PRIMARY KEY (id)) - ENGINE = MEMORY SELECT i.*, p.name AS producerName, diff --git a/modules/invoiceOut/front/index/global-invoicing/index.spec.js b/modules/invoiceOut/front/index/global-invoicing/index.spec.js index 35252c406..916364007 100644 --- a/modules/invoiceOut/front/index/global-invoicing/index.spec.js +++ b/modules/invoiceOut/front/index/global-invoicing/index.spec.js @@ -66,7 +66,9 @@ describe('InvoiceOut', () => { controller.responseHandler('accept'); - expect(controller.vnApp.showError).toHaveBeenCalledWith(`Invoice date and the max date should be filled`); + const expectedError = 'Invoice date and the max date should be filled'; + + expect(controller.vnApp.showError).toHaveBeenCalledWith(expectedError); }); it('should throw an error when fromClientId or toClientId properties are not filled in', () => { diff --git a/modules/item/back/models/expense.json b/modules/item/back/models/expense.json index 368876fbe..03147c08b 100644 --- a/modules/item/back/models/expense.json +++ b/modules/item/back/models/expense.json @@ -18,12 +18,5 @@ "isWithheld": { "type": "number" } - }, - "relations": { - "taxType": { - "type": "belongsTo", - "model": "TaxType", - "foreignKey": "taxTypeFk" - } } } \ No newline at end of file diff --git a/modules/item/front/summary/index.html b/modules/item/front/summary/index.html index dfc0b6e01..5264977f3 100644 --- a/modules/item/front/summary/index.html +++ b/modules/item/front/summary/index.html @@ -117,6 +117,23 @@ value="{{tag.value}}"> + +

+ + Description + +

+

+ Description +

+

+ {{$ctrl.summary.item.description}} +

+

{ - Self.remoteMethod('canHaveStowaway', { - description: 'Returns if a ticket can have stowaway', - accessType: 'READ', - accepts: [{ - arg: 'id', - type: 'number', - required: true, - description: 'ticket id', - http: {source: 'path'} - }], - returns: { - root: true - }, - http: { - path: `/:id/canHaveStowaway`, - verb: 'GET' - } - }); - - Self.canHaveStowaway = async(id, options) => { - const models = Self.app.models; - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - const ticket = await models.Ticket.findById(id, { - include: { - relation: 'ship', - scope: { - fields: ['id'] - } - } - }, myOptions); - - const warehouse = await models.Warehouse.findById(ticket.warehouseFk, null, myOptions); - - const hasStowaway = ticket.ship() ? true : false; - const validStowaway = warehouse && warehouse.hasStowaway && !hasStowaway; - - if (!ticket.isDeleted && validStowaway) - return true; - - return false; - }; -}; diff --git a/modules/ticket/back/methods/ticket/deleteStowaway.js b/modules/ticket/back/methods/ticket/deleteStowaway.js deleted file mode 100644 index c3e5e0db1..000000000 --- a/modules/ticket/back/methods/ticket/deleteStowaway.js +++ /dev/null @@ -1,105 +0,0 @@ - -module.exports = Self => { - Self.remoteMethodCtx('deleteStowaway', { - description: 'Deletes an stowaway', - accessType: 'WRITE', - accepts: [{ - arg: 'id', - type: 'number', - required: true, - description: 'The ticket id', - http: {source: 'path'} - }], - returns: { - root: true - }, - http: { - path: `/:id/deleteStowaway`, - verb: 'POST' - } - }); - - Self.deleteStowaway = async(ctx, id, options) => { - const models = Self.app.models; - const $t = ctx.req.__; // $translate - const myOptions = {}; - let tx; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - if (!myOptions.transaction) { - tx = await Self.beginTransaction({}); - myOptions.transaction = tx; - } - - try { - const ticket = await Self.findById(id, { - include: [{ - relation: 'ship' - }, { - relation: 'stowaway' - }, { - relation: 'client', - scope: { - include: { - relation: 'salesPersonUser', - scope: { - fields: ['id', 'name'] - } - } - } - }] - }, myOptions); - - let stowawayFk; - let shipFk; - if (ticket.stowaway()) { - shipFk = ticket.stowaway().shipFk; - stowawayFk = ticket.stowaway().id; - } else if (ticket.ship()) { - shipFk = ticket.ship().shipFk; - stowawayFk = ticket.ship().id; - } - - const stowaway = await models.Stowaway.findOne({ - where: { - id: stowawayFk, - shipFk: shipFk - } - }, myOptions); - const result = await stowaway.destroy(myOptions); - - const state = await models.State.findOne({ - where: { - code: 'BOARDING' - } - }, myOptions); - const ticketTracking = await models.TicketTracking.findOne({ - where: { - ticketFk: shipFk, - stateFk: state.id - } - }, myOptions); - - await ticketTracking.destroy(myOptions); - - const salesPerson = ticket.client().salesPersonUser(); - if (salesPerson) { - const origin = ctx.req.headers.origin; - const message = $t('This ticket is not an stowaway anymore', { - ticketId: stowawayFk, - ticketUrl: `${origin}/#!/ticket/${stowawayFk}/sale` - }); - await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message); - } - - if (tx) await tx.commit(); - - return result; - } catch (e) { - if (tx) await tx.rollback(); - throw e; - } - }; -}; diff --git a/modules/ticket/back/methods/ticket/filter.js b/modules/ticket/back/methods/ticket/filter.js index 467c88246..da8f65be2 100644 --- a/modules/ticket/back/methods/ticket/filter.js +++ b/modules/ticket/back/methods/ticket/filter.js @@ -200,22 +200,7 @@ module.exports = Self => { return {'t.routeFk': {neq: null}}; return {'t.routeFk': null}; case 'pending': - if (value) { - return {and: [ - {'st.alertLevel': 0}, - {'st.code': {nin: [ - 'OK', - 'BOARDING', - 'PRINTED', - 'PRINTED_AUTO', - 'PICKER_DESIGNED' - ]}} - ]}; - } else { - return {and: [ - {'st.alertLevel': {gt: 0}} - ]}; - } + return {'st.isNotValidated': value}; case 'id': case 'clientFk': case 'agencyModeFk': diff --git a/modules/ticket/back/methods/ticket/getPossibleStowaways.js b/modules/ticket/back/methods/ticket/getPossibleStowaways.js deleted file mode 100644 index c97e3de89..000000000 --- a/modules/ticket/back/methods/ticket/getPossibleStowaways.js +++ /dev/null @@ -1,74 +0,0 @@ -const UserError = require('vn-loopback/util/user-error'); - -module.exports = Self => { - Self.remoteMethod('getPossibleStowaways', { - description: 'Returns a list of allowed tickets for a stowaway ticket', - accessType: 'READ', - accepts: [{ - arg: 'id', - type: 'number', - required: true, - description: 'ticket id', - http: {source: 'path'} - }], - returns: { - root: true - }, - http: { - path: `/:id/getPossibleStowaways`, - verb: 'GET' - } - }); - - Self.getPossibleStowaways = async(ticketFk, options) => { - const models = Self.app.models; - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - const canHaveStowaway = await models.Ticket.canHaveStowaway(ticketFk, myOptions); - - if (!canHaveStowaway) - throw new UserError(`Can't create stowaway for this ticket`); - - const ship = await models.Ticket.findById(ticketFk, null, myOptions); - - if (!ship || !ship.shipped) - return []; - - const lowestDate = new Date(ship.shipped.getTime()); - lowestDate.setHours(0, 0, -1, 0); - - const highestDate = new Date(ship.shipped.getTime()); - highestDate.setHours(23, 59, 59); - - const possibleStowaways = await models.Ticket.find({ - where: { - id: {neq: ticketFk}, - clientFk: ship.clientFk, - addressFk: ship.addressFk, - agencyModeFk: ship.agencyModeFk, - warehouseFk: {neq: ship.warehouseFk}, - shipped: { - between: [lowestDate.toJSON(), highestDate.toJSON()] - } - }, - include: [ - {relation: 'agencyMode'}, - {relation: 'warehouse'}, - {relation: 'ticketState', - scope: { - fields: ['stateFk'], - include: { - relation: 'state', - fields: ['id', 'name'], - } - }, - }, - ] - }, myOptions); - - return possibleStowaways; - }; -}; diff --git a/modules/ticket/back/methods/ticket/setDeleted.js b/modules/ticket/back/methods/ticket/setDeleted.js index c683dcffd..cec8096a6 100644 --- a/modules/ticket/back/methods/ticket/setDeleted.js +++ b/modules/ticket/back/methods/ticket/setDeleted.js @@ -107,28 +107,9 @@ module.exports = Self => { } } } - }, { - relation: 'ship' - }, { - relation: 'stowaway' }] }, myOptions); - // Change state to "fixing" if contains an stowaway and remove the link between them - let otherTicketId; - if (ticket.stowaway()) - otherTicketId = ticket.stowaway().shipFk; - else if (ticket.ship()) - otherTicketId = ticket.ship().id; - - if (otherTicketId) { - await models.Ticket.deleteStowaway(ctx, otherTicketId, myOptions); - await models.TicketTracking.changeState(ctx, { - ticketFk: otherTicketId, - code: 'FIXING' - }, myOptions); - } - // Send notification to salesPerson const salesPersonUser = ticket.client().salesPersonUser(); if (salesPersonUser) { diff --git a/modules/ticket/back/methods/ticket/specs/canHaveStowaway.spec.js b/modules/ticket/back/methods/ticket/specs/canHaveStowaway.spec.js deleted file mode 100644 index 2bd25c2d2..000000000 --- a/modules/ticket/back/methods/ticket/specs/canHaveStowaway.spec.js +++ /dev/null @@ -1,39 +0,0 @@ -const models = require('vn-loopback/server/server').models; - -describe('ticket canHaveStowaway()', () => { - it('should return true if the ticket warehouse have hasStowaway equal 1', async() => { - const tx = await models.Ticket.beginTransaction({}); - - try { - const options = {transaction: tx}; - - const ticketId = 16; - const canStowaway = await models.Ticket.canHaveStowaway(ticketId, options); - - expect(canStowaway).toBeTruthy(); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should return false if the ticket warehouse dont have hasStowaway equal 0', async() => { - const tx = await models.Ticket.beginTransaction({}); - - try { - const options = {transaction: tx}; - - const ticketId = 10; - const canStowaway = await models.Ticket.canHaveStowaway(ticketId, options); - - expect(canStowaway).toBeFalsy(); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); -}); diff --git a/modules/ticket/back/methods/ticket/specs/deleteStowaway.spec.js b/modules/ticket/back/methods/ticket/specs/deleteStowaway.spec.js deleted file mode 100644 index 62bfc71be..000000000 --- a/modules/ticket/back/methods/ticket/specs/deleteStowaway.spec.js +++ /dev/null @@ -1,75 +0,0 @@ -const models = require('vn-loopback/server/server').models; - -describe('ticket deleteStowaway()', () => { - const shipId = 16; - const stowawayId = 17; - const ctx = { - req: { - accessToken: {userId: 18}, - headers: {origin: 'http://localhost'} - } - }; - ctx.req.__ = (value, params) => { - return params.nickname; - }; - - it(`should create an stowaway, delete it and see the states of both stowaway and ship go back to the last states`, async() => { - const tx = await models.Ticket.beginTransaction({}); - - try { - const options = {transaction: tx}; - - await models.Stowaway.rawSql(` - INSERT INTO stowaway (id, shipFk) VALUES (?, ?) - `, [stowawayId, shipId], options); - await models.Stowaway.rawSql( - `CALL ticketStateUpdate(?, ?)`, [shipId, 'BOARDING'], options); - await models.Stowaway.rawSql( - `CALL ticketStateUpdate(?, ?)`, [stowawayId, 'BOARDING'], options); - - let createdStowaways = await models.Stowaway.count({id: stowawayId, shipFk: shipId}, options); - - expect(createdStowaways).toEqual(1); - - let shipState = await models.TicketLastState.findOne({ - where: { - ticketFk: shipId - } - }, options); - let stowawayState = await models.TicketLastState.findOne({ - where: { - ticketFk: stowawayId - } - }, options); - - expect(shipState.name).toEqual('Embarcando'); - expect(stowawayState.name).toEqual('Embarcando'); - - await models.Ticket.deleteStowaway(ctx, shipId, options); - await models.Ticket.deleteStowaway(ctx, stowawayId, options); - - createdStowaways = await models.Stowaway.count({id: stowawayId, shipFk: shipId}, options); - - expect(createdStowaways).toEqual(0); - - shipState = await models.TicketLastState.findOne({ - where: { - ticketFk: shipId - } - }, options); - stowawayState = await models.TicketLastState.findOne({ - where: { - ticketFk: stowawayId - } - }, options); - - expect(shipState.name).toEqual('OK'); - expect(stowawayState.name).toEqual('Libre'); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); -}); diff --git a/modules/ticket/back/methods/ticket/specs/filter.spec.js b/modules/ticket/back/methods/ticket/specs/filter.spec.js index 020bc5747..c3dc40092 100644 --- a/modules/ticket/back/methods/ticket/specs/filter.spec.js +++ b/modules/ticket/back/methods/ticket/specs/filter.spec.js @@ -153,7 +153,7 @@ describe('ticket filter()', () => { const secondRow = result[1]; const thirdRow = result[2]; - expect(result.length).toEqual(12); + expect(result.length).toEqual(17); expect(firstRow.state).toEqual('Entregado'); expect(secondRow.state).toEqual('Entregado'); expect(thirdRow.state).toEqual('Entregado'); diff --git a/modules/ticket/back/methods/ticket/specs/getPossibleStowaways.spec.js b/modules/ticket/back/methods/ticket/specs/getPossibleStowaways.spec.js deleted file mode 100644 index ed1a327d4..000000000 --- a/modules/ticket/back/methods/ticket/specs/getPossibleStowaways.spec.js +++ /dev/null @@ -1,60 +0,0 @@ -const models = require('vn-loopback/server/server').models; -let UserError = require('vn-loopback/util/user-error'); - -describe('ticket getPossibleStowaways()', () => { - it(`should throw an error if Can't create stowaway for this ticket`, async() => { - const tx = await models.Ticket.beginTransaction({}); - - let error; - - try { - const options = {transaction: tx}; - - const ticketId = 10; - await models.Ticket.getPossibleStowaways(ticketId, options); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - error = e; - } - - expect(error).toEqual(new UserError(`Can't create stowaway for this ticket`)); - }); - - it('should return an empty list of tickets for a valid ticket', async() => { - const tx = await models.Ticket.beginTransaction({}); - - try { - const options = {transaction: tx}; - - const ticketId = 12; - const possibleStowaways = await models.Ticket.getPossibleStowaways(ticketId, options); - - expect(possibleStowaways.length).toEqual(0); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should return allowed list of tickets for a valid ticket', async() => { - const tx = await models.Ticket.beginTransaction({}); - - try { - const options = {transaction: tx}; - - const ticketId = 16; - const possibleStowaways = await models.Ticket.getPossibleStowaways(ticketId, options); - - expect(possibleStowaways.length).toEqual(1); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); -}); diff --git a/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js b/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js index 4551377df..132b1938d 100644 --- a/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js +++ b/modules/ticket/back/methods/ticket/specs/setDeleted.spec.js @@ -98,92 +98,4 @@ describe('ticket setDeleted()', () => { throw e; } }); - - it('should delete ticket, remove stowaway and itemshelving then change stowaway state to "FIXING" ', async() => { - pending('test excluded by task #3693'); - const tx = await models.Ticket.beginTransaction({}); - - try { - const options = {transaction: tx}; - - spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ - active: activeCtx - }); - const ctx = { - req: { - accessToken: {userId: employeeUser}, - headers: { - origin: 'http://localhost:5000' - }, - __: () => {} - } - }; - - const sampleTicket = await models.Ticket.findById(12); - const sampleStowaway = await models.Ticket.findById(13); - - sampleTicket.id = undefined; - const shipTicket = await models.Ticket.create(sampleTicket, options); - - sampleStowaway.id = undefined; - const stowawayTicket = await models.Ticket.create(sampleStowaway, options); - - await models.Stowaway.rawSql(` - INSERT INTO vn.stowaway(id, shipFk) - VALUES (?, ?)`, [stowawayTicket.id, shipTicket.id], options); - - const boardingState = await models.State.findOne({ - where: { - code: 'BOARDING' - } - }, options); - - await models.TicketTracking.create({ - ticketFk: stowawayTicket.id, - stateFk: boardingState.id, - workerFk: ctx.req.accessToken.userId - }, options); - - const okState = await models.State.findOne({ - where: { - code: 'OK' - } - }, options); - - await models.TicketTracking.create({ - ticketFk: shipTicket.id, - stateFk: okState.id, - workerFk: ctx.req.accessToken.userId - }, options); - - let stowawayTicketState = await models.TicketState.findOne({ - where: { - ticketFk: stowawayTicket.id - } - }, options); - - let stowaway = await models.Stowaway.findById(shipTicket.id, null, options); - - expect(stowaway).toBeDefined(); - expect(stowawayTicketState.code).toEqual('BOARDING'); - - await models.Ticket.setDeleted(ctx, shipTicket.id, options); - - stowawayTicketState = await models.TicketState.findOne({ - where: { - ticketFk: stowawayTicket.id - } - }, options); - - stowaway = await models.Stowaway.findById(shipTicket.id, null, options); - - expect(stowaway).toBeNull(); - expect(stowawayTicketState.code).toEqual('FIXING'); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); }); diff --git a/modules/ticket/back/model-config.json b/modules/ticket/back/model-config.json index e75c7415e..0908503a5 100644 --- a/modules/ticket/back/model-config.json +++ b/modules/ticket/back/model-config.json @@ -38,9 +38,6 @@ "State":{ "dataSource": "vn" }, - "Stowaway": { - "dataSource": "vn" - }, "Ticket": { "dataSource": "vn" }, diff --git a/modules/ticket/back/models/stowaway.js b/modules/ticket/back/models/stowaway.js deleted file mode 100644 index 780b6b31c..000000000 --- a/modules/ticket/back/models/stowaway.js +++ /dev/null @@ -1,24 +0,0 @@ -const LoopBackContext = require('loopback-context'); -const UserError = require('vn-loopback/util/user-error'); - -module.exports = function(Self) { - Self.observe('before save', async function(ctx) { - const models = Self.app.models; - const canHaveStowaway = await models.Ticket.canHaveStowaway(ctx.instance.shipFk); - - if (!canHaveStowaway) - throw new UserError(`Can't create stowaway for this ticket`); - - if (ctx.isNewInstance) { - let where = { - code: 'BOARDING' - }; - let state = await models.State.findOne({where}); - let params = {ticketFk: ctx.instance.shipFk, stateFk: state.id}; - const loopBackContext = LoopBackContext.getCurrentContext(); - - let httpCtx = {req: loopBackContext.active}; - await models.TicketTracking.changeState(httpCtx, params); - } - }); -}; diff --git a/modules/ticket/back/models/stowaway.json b/modules/ticket/back/models/stowaway.json deleted file mode 100644 index ef3aeb40d..000000000 --- a/modules/ticket/back/models/stowaway.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "Stowaway", - "base": "VnModel", - "options": { - "mysql": { - "table": "stowaway" - } - }, - "properties": { - "id": { - "id": true, - "type": "number", - "forceId": false - }, - "shipFk": { - "type": "number", - "required": false - }, - "created":{ - "type": "date", - "required": false - } - }, - "relations": { - "ship": { - "type": "belongsTo", - "model": "Ticket", - "foreignKey": "shipFk" - }, - "ticket": { - "type": "belongsTo", - "model": "Ticket", - "foreignKey": "id" - } - } -} diff --git a/modules/ticket/back/models/ticket.js b/modules/ticket/back/models/ticket.js index b217eae4d..300893968 100644 --- a/modules/ticket/back/models/ticket.js +++ b/modules/ticket/back/models/ticket.js @@ -14,7 +14,6 @@ module.exports = Self => { require('../methods/ticket/getSales')(Self); require('../methods/ticket/getSalesPersonMana')(Self); require('../methods/ticket/filter')(Self); - require('../methods/ticket/getPossibleStowaways')(Self); require('../methods/ticket/canBeInvoiced')(Self); require('../methods/ticket/makeInvoice')(Self); require('../methods/ticket/updateEditableTicket')(Self); @@ -23,9 +22,7 @@ module.exports = Self => { require('../methods/ticket/uploadFile')(Self); require('../methods/ticket/addSale')(Self); require('../methods/ticket/transferSales')(Self); - require('../methods/ticket/canHaveStowaway')(Self); require('../methods/ticket/recalculateComponents')(Self); - require('../methods/ticket/deleteStowaway')(Self); require('../methods/ticket/sendSms')(Self); require('../methods/ticket/isLocked')(Self); require('../methods/ticket/freightCost')(Self); diff --git a/modules/ticket/back/models/ticket.json b/modules/ticket/back/models/ticket.json index 65127a78c..80604a713 100644 --- a/modules/ticket/back/models/ticket.json +++ b/modules/ticket/back/models/ticket.json @@ -69,16 +69,6 @@ "model": "Client", "foreignKey": "clientFk" }, - "ship": { - "type": "hasOne", - "model": "Stowaway", - "foreignKey": "shipFk" - }, - "stowaway": { - "type": "hasOne", - "model": "Stowaway", - "foreignKey": "id" - }, "warehouse": { "type": "belongsTo", "model": "Warehouse", diff --git a/modules/ticket/front/card/index.js b/modules/ticket/front/card/index.js index 6e38039e2..e63fb9b15 100644 --- a/modules/ticket/front/card/index.js +++ b/modules/ticket/front/card/index.js @@ -6,18 +6,15 @@ class Controller extends ModuleCard { let filter = { include: [ { - relation: 'address'}, + relation: 'address' + }, { - relation: 'ship'}, - { - relation: 'stowaway'}, + relation: 'zone' + }, { relation: 'warehouse', scope: {fields: ['name']} }, - { - relation: 'zone', - }, { relation: 'invoiceOut', scope: {fields: ['id']} @@ -47,7 +44,8 @@ class Controller extends ModuleCard { } }, }, - }, { + }, + { relation: 'ticketState', scope: { fields: ['stateFk'], diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html index 1dcfd669f..cfd817c45 100644 --- a/modules/ticket/front/descriptor-menu/index.html +++ b/modules/ticket/front/descriptor-menu/index.html @@ -103,20 +103,6 @@ translate> SMS Minimum import - - Add stowaway - - - Delete stowaway - - - - - - - - - this.ticket = res.data) .then(() => { - this.canStowaway(); this.isTicketEditable(); this.hasDocuware(); }); @@ -228,27 +228,6 @@ class Controller extends Section { this.$.sms.open(); } - canStowaway() { - this.canShowStowaway = false; - if (!this.isTicketModule || !this.ticket) return; - - this.$http.get(`Tickets/${this.id}/canHaveStowaway`) - .then(res => this.canShowStowaway = !!res.data); - } - - get canDeleteStowaway() { - if (!this.ticket || !this.isTicketModule) - return false; - - return this.ticket.stowaway || this.ticket.ship; - } - - deleteStowaway() { - return this.$http.post(`Tickets/${this.id}/deleteStowaway`) - .then(() => this.reload()) - .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))); - } - makeInvoice() { const params = {ticketsIds: [this.id]}; return this.$http.post(`Tickets/makeInvoice`, params) diff --git a/modules/ticket/front/descriptor-menu/index.spec.js b/modules/ticket/front/descriptor-menu/index.spec.js index af377d8ea..65da73ca0 100644 --- a/modules/ticket/front/descriptor-menu/index.spec.js +++ b/modules/ticket/front/descriptor-menu/index.spec.js @@ -231,23 +231,6 @@ describe('Ticket Component vnTicketDescriptorMenu', () => { }); }); - describe('canStowaway()', () => { - it('should make a query and return if the ticket can be stowawayed', () => { - $httpBackend.expect('GET', `Tickets/${ticket.id}/canHaveStowaway`).respond(true); - controller.canStowaway(); - $httpBackend.flush(); - - expect(controller.canShowStowaway).toBeTruthy(); - }); - - it('should not make a query if is not on the ticket module', () => { - $state.getCurrentPath = () => [null, {state: {name: 'client'}}]; - controller.canStowaway(); - - expect(controller.canShowStowaway).toBeFalsy(); - }); - }); - describe('recalculateComponents()', () => { it('should make a query and show a success message', () => { jest.spyOn(controller, 'reload').mockReturnThis(); diff --git a/modules/ticket/front/descriptor/addStowaway.html b/modules/ticket/front/descriptor/addStowaway.html deleted file mode 100644 index 44d262d51..000000000 --- a/modules/ticket/front/descriptor/addStowaway.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - Ticket id - Shipped - Agency - Warehouse - State - - - - - {{ticket.id}} - {{ticket.landed | date: 'dd/MM/yyyy'}} - {{ticket.agencyMode.name}} - {{ticket.warehouse.name}} - {{ticket.ticketState.state.name}} - - - - - - - \ No newline at end of file diff --git a/modules/ticket/front/descriptor/addStowaway.js b/modules/ticket/front/descriptor/addStowaway.js deleted file mode 100644 index c88bda0af..000000000 --- a/modules/ticket/front/descriptor/addStowaway.js +++ /dev/null @@ -1,32 +0,0 @@ -import ngModule from '../module'; -import Component from 'core/lib/component'; -import './style.scss'; - -class Controller extends Component { - addStowaway(stowaway) { - let params = {id: stowaway.id, shipFk: this.ticket.id}; - this.$http.post(`Stowaways/`, params) - .then(() => this.cardReload()) - .then(() => { - this.vnApp.showSuccess(this.$t('Data saved!')); - this.$.dialog.hide(); - }); - } - - show() { - this.$.dialog.show(); - } - - hide() { - this.$.dialog.hide(); - } -} - -ngModule.vnComponent('vnAddStowaway', { - template: require('./addStowaway.html'), - controller: Controller, - bindings: { - ticket: '<', - cardReload: '&?' - } -}); diff --git a/modules/ticket/front/descriptor/index.html b/modules/ticket/front/descriptor/index.html index 2c27b19cd..75bcd2801 100644 --- a/modules/ticket/front/descriptor/index.html +++ b/modules/ticket/front/descriptor/index.html @@ -93,36 +93,6 @@ icon="icon-basketadd"> -
- - -
-
- - -
- -
- -
diff --git a/modules/ticket/front/descriptor/locale/es.yml b/modules/ticket/front/descriptor/locale/es.yml index 2a7bf360f..8ab88ce09 100644 --- a/modules/ticket/front/descriptor/locale/es.yml +++ b/modules/ticket/front/descriptor/locale/es.yml @@ -1,12 +1,4 @@ -Ship: Barco -Stowaway: Polizón Cliente: Client -Ship stowaways: Polizones del barco -Stowaways to add: Polizones a añadir -Stowaways of the ticket: Polizones del ticket -Add stowaway: Añadir polizón -Delete stowaway: Eliminar polizón -Are you sure you want to delete this stowaway?: ¿Seguro que quieres eliminar este polizón? Are you sure you want to send it?: ¿Seguro que quieres enviarlo? Show pallet report: Ver hoja de pallet Change shipped hour: Cambiar hora de envío diff --git a/modules/ticket/front/descriptor/style.scss b/modules/ticket/front/descriptor/style.scss index 1a69feeff..f083f41fc 100644 --- a/modules/ticket/front/descriptor/style.scss +++ b/modules/ticket/front/descriptor/style.scss @@ -1,11 +1,5 @@ @import "variables"; -.add-stowaway { - vn-data-viewer { - width: 640px - } -} - vn-dialog.modal-form { section.header { background-color: $color-main; diff --git a/modules/ticket/front/index.js b/modules/ticket/front/index.js index 01d1d7242..85a03ffb6 100644 --- a/modules/ticket/front/index.js +++ b/modules/ticket/front/index.js @@ -5,7 +5,6 @@ import './index/'; import './search-panel'; import './card'; import './descriptor'; -import './descriptor/addStowaway'; import './descriptor-popover'; import './descriptor-menu'; import './create/card'; diff --git a/modules/worker/back/methods/worker-time-control/addTimeEntry.js b/modules/worker/back/methods/worker-time-control/addTimeEntry.js index 06356cdaf..fef3cf223 100644 --- a/modules/worker/back/methods/worker-time-control/addTimeEntry.js +++ b/modules/worker/back/methods/worker-time-control/addTimeEntry.js @@ -46,30 +46,11 @@ module.exports = Self => { if (isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss)) throw new UserError(`You don't have enough privileges`); - const minTime = new Date(args.timed); - minTime.setHours(0, 0, 0, 0); + query = `CALL vn.workerTimeControl_clockIn(?,?,?)`; + const [response] = await Self.rawSql(query, [workerId, args.timed, args.direction], myOptions); + if (response[0] && response[0].error) + throw new UserError(response[0].error); - query = `SELECT * FROM vn.workerLabour WHERE workerFk = ? AND (ended >= ? OR ended IS NULL);`; - const [workerLabour] = await Self.rawSql(query, [workerId, minTime]); - const absence = await models.Calendar.findOne({ - where: { - businessFk: workerLabour.businessFk, - dated: minTime - } - }); - if (absence) { - const absenceType = await models.AbsenceType.findById(absence.dayOffTypeFk, null, myOptions); - const isNotHalfAbsence = absenceType.code != 'halfHoliday' - && absenceType.code != 'halfPaidLeave' - && absenceType.code != 'halfFurlough'; - if (isNotHalfAbsence) - throw new UserError(`The worker has a marked absence that day`); - } - return models.WorkerTimeControl.create({ - userFk: workerId, - direction: args.direction, - timed: args.timed, - manual: true - }, myOptions); + return response; }; }; diff --git a/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js b/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js index 69fcbe90c..e1e0feced 100644 --- a/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js +++ b/modules/worker/back/methods/worker-time-control/specs/timeEntry.spec.js @@ -1,6 +1,6 @@ -const app = require('vn-loopback/server/server'); +/* eslint max-len: ["error", { "code": 150 }]*/ +const models = require('vn-loopback/server/server').models; const LoopBackContext = require('loopback-context'); -const models = app.models; describe('workerTimeControl add/delete timeEntry()', () => { const HHRRId = 37; @@ -8,6 +8,14 @@ describe('workerTimeControl add/delete timeEntry()', () => { const employeeId = 1; const salesPersonId = 1106; const salesBossId = 19; + const hankPymId = 1107; + const jessicaJonesId = 1110; + const monday = 1; + const tuesday = 2; + const thursday = 4; + const friday = 5; + const saturday = 6; + const sunday = 7; const activeCtx = { accessToken: {userId: 50}, }; @@ -19,190 +27,675 @@ 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; + describe('as Role errors', () => { + 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 error; - try { - ctx.args = {timed: new Date(), direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId); - } catch (e) { - error = e; - } + try { + ctx.args = {timed: new Date(), direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId); + } catch (e) { + error = e; + } - expect(error).toBeDefined(); - expect(error.statusCode).toBe(400); - expect(error.message).toBe(`You don't have enough privileges`); + expect(error).toBeDefined(); + expect(error.statusCode).toBe(400); + expect(error.message).toBe(`You don't have enough privileges`); + }); + + 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; + + try { + ctx.args = {timed: new Date(), direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error.statusCode).toBe(400); + expect(error.message).toBe(`You don't have enough privileges`); + }); + + it('should add if the current user is team boss and the target user is himself', async() => { + activeCtx.accessToken.userId = teamBossId; + const workerId = teamBossId; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + try { + const options = {transaction: tx}; + + const todayAtOne = new Date(); + todayAtOne.setHours(1, 0, 0, 0); + + ctx.args = {timed: todayAtOne, direction: 'in'}; + const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + 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; + const tx = await models.WorkerTimeControl.beginTransaction({}); + try { + const options = {transaction: tx}; + + const todayAtOne = new Date(); + todayAtOne.setHours(1, 0, 0, 0); + + ctx.args = {timed: todayAtOne, direction: 'in'}; + const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + activeCtx.accessToken.userId = salesPersonId; + await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error).toBeDefined(); + expect(error.statusCode).toBe(400); + expect(error.message).toBe(`You don't have enough privileges`); + }); + + it('should delete the created time entry for the team boss as himself', async() => { + activeCtx.accessToken.userId = teamBossId; + const workerId = teamBossId; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + try { + const options = {transaction: tx}; + + const todayAtOne = new Date(); + todayAtOne.setHours(1, 0, 0, 0); + + ctx.args = {timed: todayAtOne, direction: 'in'}; + const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + expect(createdTimeEntry.id).toBeDefined(); + + await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options); + + const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options); + + 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; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + try { + const options = {transaction: tx}; + + const todayAtOne = new Date(); + todayAtOne.setHours(1, 0, 0, 0); + + ctx.args = {timed: todayAtOne, direction: 'in'}; + const [createdTimeEntry] = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + expect(createdTimeEntry.id).toBeDefined(); + + await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options); + + const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options); + + expect(deletedTimeEntry).toBeNull(); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + 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 todayAtOne = new Date(); + todayAtOne.setHours(1, 0, 0, 0); + + ctx.args = {timed: todayAtOne, 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; + } + }); }); - 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; + describe('WorkerTimeControl_clockIn calls', () => { + it('should fail to add a time entry if the target user has an absence that day', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; + const date = new Date(); + date.setDate(date.getDate() - 16); + date.setHours(8, 0, 0); + let error; - try { - ctx.args = {timed: new Date(), direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId); - } catch (e) { - error = e; - } - - expect(error).toBeDefined(); - expect(error.statusCode).toBe(400); - expect(error.message).toBe(`You don't have enough privileges`); - }); - - it('should add if the current user is team boss and the target user is a himself', async() => { - activeCtx.accessToken.userId = teamBossId; - const workerId = teamBossId; - - const tx = await models.WorkerTimeControl.beginTransaction({}); - try { + const tx = await models.WorkerTimeControl.beginTransaction({}); const options = {transaction: tx}; + try { + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - const todayAtSix = new Date(); - todayAtSix.setHours(18, 30, 0, 0); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } - ctx.args = {timed: todayAtSix, direction: 'in'}; - const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + expect(error.message).toBe(`No está permitido trabajar`); + }); - expect(createdTimeEntry.id).toBeDefined(); + it('should fail to add a time entry for a worker without an existing contract', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; + const date = new Date(); + date.setFullYear(date.getFullYear() - 2); + let error; - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); + const tx = await models.WorkerTimeControl.beginTransaction({}); + try { + const options = {transaction: tx}; + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - it('should fail to add a time entry if the target user has absent that day', async() => { - activeCtx.accessToken.userId = salesBossId; - const workerId = salesPersonId; - let error; + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } - const calendar = await app.models.Calendar.findById(3); + expect(error.message).toBe(`No hay un contrato en vigor`); + }); - try { - ctx.args = {timed: new Date(calendar.dated), direction: 'in'}; - await models.WorkerTimeControl.addTimeEntry(ctx, workerId); - } catch (e) { - error = e; - } + describe('direction errors', () => { + it('should throw an error when trying "in" direction twice', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; - expect(error.message).toBe(`The worker has a marked absence that day`); - }); + let date = new Date(); + date.setDate(date.getDate() - 21); + date = weekDay(date, monday); + let error; - it('should try but fail to delete his own time entry', async() => { - activeCtx.accessToken.userId = salesBossId; - const workerId = salesBossId; + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - let error; - const tx = await models.WorkerTimeControl.beginTransaction({}); - try { - const options = {transaction: tx}; + try { + date.setHours(10, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - const todayAtSeven = new Date(); - todayAtSeven.setHours(19, 30, 0, 0); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } - ctx.args = {timed: todayAtSeven, direction: 'in'}; - const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + expect(error.message).toBe(`Dirección incorrecta`); + }); - activeCtx.accessToken.userId = salesPersonId; - await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options); + it('should throw an error when trying "in" direction after insert "in" and "middle"', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; - await tx.rollback(); - } catch (e) { - error = e; - await tx.rollback(); - } + let date = new Date(); + date.setDate(date.getDate() - 21); + date = weekDay(date, monday); + let error; - expect(error).toBeDefined(); - expect(error.statusCode).toBe(400); - expect(error.message).toBe(`You don't have enough privileges`); - }); + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; - it('should delete the created time entry for the team boss as himself', async() => { - activeCtx.accessToken.userId = teamBossId; - const workerId = teamBossId; + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(9, 0, 0); + ctx.args = {timed: date, direction: 'middle'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - const tx = await models.WorkerTimeControl.beginTransaction({}); - try { - const options = {transaction: tx}; + try { + date.setHours(10, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - const todayAtFive = new Date(); - todayAtFive.setHours(17, 30, 0, 0); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } - ctx.args = {timed: todayAtFive, direction: 'in'}; - const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + expect(error.message).toBe(`Dirección incorrecta`); + }); - expect(createdTimeEntry.id).toBeDefined(); + it('Should throw an error when trying "out" before closing a "middle" couple', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; - await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options); + let date = new Date(); + date.setDate(date.getDate() - 21); + date = weekDay(date, monday); + let error; - const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options); + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; - expect(deletedTimeEntry).toBeNull(); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(9, 0, 0); + ctx.args = {timed: date, direction: 'middle'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - it('should delete the created time entry for the team boss as HHRR', async() => { - activeCtx.accessToken.userId = HHRRId; - const workerId = teamBossId; + try { + date.setHours(10, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - const tx = await models.WorkerTimeControl.beginTransaction({}); - try { - const options = {transaction: tx}; + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } - const todayAtFive = new Date(); - todayAtFive.setHours(17, 30, 0, 0); + expect(error.message).toBe(`Dirección incorrecta`); + }); - ctx.args = {timed: todayAtFive, direction: 'in'}; - const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + it('should throw an error when trying "middle" after "out"', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; - expect(createdTimeEntry.id).toBeDefined(); + let date = new Date(); + date.setDate(date.getDate() - 21); + date = weekDay(date, monday); + let error; - await models.WorkerTimeControl.deleteTimeEntry(ctx, createdTimeEntry.id, options); + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; - const deletedTimeEntry = await models.WorkerTimeControl.findById(createdTimeEntry.id, null, options); + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(9, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - expect(deletedTimeEntry).toBeNull(); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); + try { + date.setHours(10, 0, 0); + ctx.args = {timed: date, direction: 'middle'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - it('should edit the created time entry for the team boss as HHRR', async() => { - activeCtx.accessToken.userId = HHRRId; - const workerId = teamBossId; + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } - const tx = await models.WorkerTimeControl.beginTransaction({}); - try { - const options = {transaction: tx}; + expect(error.message).toBe(`Dirección incorrecta`); + }); - const todayAtFive = new Date(); - todayAtFive.setHours(17, 30, 0, 0); + it('should throw an error when trying "out" direction twice', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; - ctx.args = {timed: todayAtFive, direction: 'in'}; - const createdTimeEntry = await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + let date = new Date(); + date.setDate(date.getDate() - 21); + date = weekDay(date, monday); + let error; - expect(createdTimeEntry.id).toBeDefined(); + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; - ctx.args = {direction: 'out'}; - const updatedTimeEntry = await models.WorkerTimeControl.updateTimeEntry(ctx, createdTimeEntry.id, options); + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(9, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); - expect(updatedTimeEntry.direction).toEqual('out'); - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } + try { + date.setHours(10, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Dirección incorrecta`); + }); + }); + + describe('12h rest', () => { + it('should throw an error when the 12h rest is not fulfilled yet', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; + + let date = new Date(); + date.setDate(date.getDate() - 21); + date = weekDay(date, monday); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(16, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date = weekDay(date, tuesday); + date.setHours(4, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Descanso diario 12h.`); + }); + + it('should not fail as the 12h rest is fulfilled', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; + + let date = new Date(); + date.setDate(date.getDate() - 21); + date = weekDay(date, monday); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(16, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date = weekDay(date, tuesday); + date.setHours(4, 1, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error).not.toBeDefined; + }); + }); + + describe('for 3500kg drivers with enforced 9h rest', () => { + it('should throw an error when the 9h enforced rest is not fulfilled', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = jessicaJonesId; + + let date = new Date(); + date.setDate(date.getDate() - 21); + date = weekDay(date, monday); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(16, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date = weekDay(date, tuesday); + date.setHours(1, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Descanso diario 9h.`); + }); + + it('should not fail when the 9h enforced rest is fulfilled', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = jessicaJonesId; + + let date = new Date(); + date.setDate(date.getDate() - 21); + date = weekDay(date, monday); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + date.setHours(16, 0, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date = weekDay(date, tuesday); + date.setHours(1, 1, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error).not.toBeDefined; + }); + }); + + describe('for 36h weekly rest', () => { + it('should throw an error when the 36h weekly rest is not fulfilled', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; + + let date = new Date(); + date.setMonth(date.getMonth() - 2); + date.setDate(1); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + await populateWeek(date, monday, sunday, ctx, workerId, options); + date = nextWeek(date); + await populateWeek(date, monday, thursday, ctx, workerId, options); + date = weekDay(date, friday); + date.setHours(7, 59, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + try { + date.setHours(8, 1, 0); + ctx.args = {timed: date, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Descanso semanal 36h. / 72h.`); + }); + + it('should throw an error when the 36h weekly rest is not fulfilled again', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; + + let date = new Date(); + date.setMonth(date.getMonth() - 2); + date.setDate(1); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + await populateWeek(date, monday, sunday, ctx, workerId, options); + date = nextWeek(date); + await populateWeek(date, monday, thursday, ctx, workerId, options); + + try { + date = weekDay(date, saturday); + date.setHours(3, 59, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Descanso semanal 36h. / 72h.`); + }); + }); + + describe('for 72h weekly rest', () => { + it('should throw when the 72h weekly rest is not fulfilled yet', async() => { + activeCtx.accessToken.userId = salesBossId; + const workerId = hankPymId; + + let date = new Date(); + date.setMonth(date.getMonth() - 2); + date.setDate(1); + let error; + + const tx = await models.WorkerTimeControl.beginTransaction({}); + const options = {transaction: tx}; + + await populateWeek(date, monday, sunday, ctx, workerId, options); + date = nextWeek(date); + await populateWeek(date, monday, thursday, ctx, workerId, options); + date = nextWeek(date); + await populateWeek(date, monday, friday, ctx, workerId, options); + date = nextWeek(date); + await populateWeek(date, monday, saturday, ctx, workerId, options); + date = nextWeek(date); + await populateWeek(date, monday, saturday, ctx, workerId, options); + date = lastWeek(date); + + try { + date = weekDay(date, sunday); + date.setHours(8, 0, 0); + ctx.args = {timed: date, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + error = e; + } + + expect(error.message).toBe(`Descanso semanal 36h. / 72h.`); + }); + }); }); }); + +function weekDay(date, dayToSet) { + const currentDay = date.getDay(); + const distance = dayToSet - currentDay; + + date.setDate(date.getDate() + distance); + return date; +} + +function nextWeek(date) { + const sunday = 7; + const currentDay = date.getDay(); + let newDate = date; + if (currentDay != 0) + newDate = weekDay(date, sunday); + + newDate.setDate(newDate.getDate() + 1); + return newDate; +} + +function lastWeek(date) { + const monday = 1; + newDate = weekDay(date, monday); + + newDate.setDate(newDate.getDate() - 1); + return newDate; +} + +async function populateWeek(date, dayStart, dayEnd, ctx, workerId, options) { + const dateStart = new Date(weekDay(date, dayStart)); + const dateEnd = new Date(dateStart); + dateEnd.setDate(dateStart.getDate() + dayEnd); + + for (let i = dayStart; i <= dayEnd; i++) { + dateStart.setHours(8, 0, 0); + ctx.args = {timed: dateStart, direction: 'in'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + dateStart.setHours(16, 0, 0); + ctx.args = {timed: dateStart, direction: 'out'}; + await models.WorkerTimeControl.addTimeEntry(ctx, workerId, options); + dateStart.setDate(dateStart.getDate() + 1); + } +} diff --git a/modules/zone/back/methods/agency/specs/getLanded.spec.js b/modules/zone/back/methods/agency/specs/getLanded.spec.js index 3f239539f..c199b2ba6 100644 --- a/modules/zone/back/methods/agency/specs/getLanded.spec.js +++ b/modules/zone/back/methods/agency/specs/getLanded.spec.js @@ -1,4 +1,4 @@ -const app = require('vn-loopback/server/server'); +const models = require('vn-loopback/server/server').models; describe('agency getLanded()', () => { it('should return a landing date', async() => { @@ -9,12 +9,12 @@ describe('agency getLanded()', () => { const agencyModeFk = 7; const warehouseFk = 1; - const tx = await app.models.Zone.beginTransaction({}); + const tx = await models.Zone.beginTransaction({}); try { const options = {transaction: tx}; - const result = await app.models.Agency.getLanded(ctx, shipped, addressFk, agencyModeFk, warehouseFk, options); + const result = await models.Agency.getLanded(ctx, shipped, addressFk, agencyModeFk, warehouseFk, options); expect(result.landed).toBeDefined(); diff --git a/print/templates/reports/driver-route/driver-route.html b/print/templates/reports/driver-route/driver-route.html index 5d840958d..600c49970 100644 --- a/print/templates/reports/driver-route/driver-route.html +++ b/print/templates/reports/driver-route/driver-route.html @@ -141,9 +141,8 @@ -
+

{{ticket.description}}

-

{{$t('stowaway')}}: {{ticket.shipFk}}

diff --git a/print/templates/reports/driver-route/locale/es.yml b/print/templates/reports/driver-route/locale/es.yml index 4c922ba64..3fb6b6885 100644 --- a/print/templates/reports/driver-route/locale/es.yml +++ b/print/templates/reports/driver-route/locale/es.yml @@ -20,7 +20,6 @@ phone: Teléfono warehouse: Almacén salesPerson: Comercial import: Importe -stowaway: Encajado dentro del ticket route: Ruta routeId: Ruta {0} ticket: Ticket \ No newline at end of file diff --git a/print/templates/reports/driver-route/sql/tickets.sql b/print/templates/reports/driver-route/sql/tickets.sql index 8806a0473..09e73819b 100644 --- a/print/templates/reports/driver-route/sql/tickets.sql +++ b/print/templates/reports/driver-route/sql/tickets.sql @@ -17,7 +17,6 @@ SELECT 0 AS import, am.name ticketAgency, tob.description, - s.shipFk, u.nickName salesPersonName, ipkg.itemPackingTypes FROM route r @@ -30,7 +29,6 @@ FROM route r LEFT JOIN province p ON a.provinceFk = p.id LEFT JOIN warehouse wh ON wh.id = t.warehouseFk LEFT JOIN agencyMode am ON am.id = t.agencyModeFk - LEFT JOIN stowaway s ON s.id = t.id LEFT JOIN ( SELECT t.id AS ticketFk, GROUP_CONCAT(DISTINCT(i.itemPackingTypeFk)) AS itemPackingTypes