From 8fb674819a925ac24015bacdde707a66c8229e15 Mon Sep 17 00:00:00 2001 From: jgallego Date: Mon, 21 Sep 2020 10:35:39 +0200 Subject: [PATCH 01/18] ticket service --- .../{00-entryLog.sql => 00-entryLog copy.sql} | 0 .../10220-back2school/01-ticketService.sql | 9 +++++++++ e2e/helpers/selectors.js | 2 -- e2e/paths/05-ticket/13_services.spec.js | 8 -------- .../back/models/ticket-service-type.json | 1 - modules/ticket/front/services/index.html | 18 ------------------ 6 files changed, 9 insertions(+), 29 deletions(-) rename db/changes/10220-back2school/{00-entryLog.sql => 00-entryLog copy.sql} (100%) create mode 100644 db/changes/10220-back2school/01-ticketService.sql diff --git a/db/changes/10220-back2school/00-entryLog.sql b/db/changes/10220-back2school/00-entryLog copy.sql similarity index 100% rename from db/changes/10220-back2school/00-entryLog.sql rename to db/changes/10220-back2school/00-entryLog copy.sql diff --git a/db/changes/10220-back2school/01-ticketService.sql b/db/changes/10220-back2school/01-ticketService.sql new file mode 100644 index 000000000..ea2d588bb --- /dev/null +++ b/db/changes/10220-back2school/01-ticketService.sql @@ -0,0 +1,9 @@ +ALTER TABLE `vn`.`ticketService` +DROP FOREIGN KEY `ticketServiceIvaGroup`; +ALTER TABLE `vn`.`ticketService` +CHANGE COLUMN `taxClassFk` `taxClassFk` TINYINT(3) UNSIGNED NOT NULL DEFAULT 2 ; +ALTER TABLE `vn`.`ticketService` +ADD CONSTRAINT `ticketServiceIvaGroup` + FOREIGN KEY (`taxClassFk`) + REFERENCES `vn`.`taxClass` (`id`) + ON UPDATE CASCADE; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index e1189ca50..8f66a3689 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -556,10 +556,8 @@ export default { firstServiceType: 'vn-ticket-service vn-autocomplete[ng-model="service.ticketServiceTypeFk"]', firstQuantity: 'vn-ticket-service vn-input-number[ng-model="service.quantity"]', firstPrice: 'vn-ticket-service vn-horizontal:nth-child(1) vn-input-number[ng-model="service.price"]', - firstVatType: 'vn-ticket-service vn-autocomplete[label="Tax class"]', fistDeleteServiceButton: 'vn-ticket-service form vn-horizontal:nth-child(1) vn-icon-button[icon="delete"]', newServiceTypeName: '.vn-dialog.shown vn-textfield[ng-model="newServiceType.name"]', - newServiceTypeExpense: '.vn-dialog.shown vn-autocomplete[ng-model="newServiceType.expenseFk"]', serviceLine: 'vn-ticket-service > form > vn-card > vn-one:nth-child(2) > vn-horizontal', saveServiceButton: 'button[type=submit]', saveServiceTypeButton: '.vn-dialog.shown tpl-buttons > button' diff --git a/e2e/paths/05-ticket/13_services.spec.js b/e2e/paths/05-ticket/13_services.spec.js index 08b9219a5..8102d9479 100644 --- a/e2e/paths/05-ticket/13_services.spec.js +++ b/e2e/paths/05-ticket/13_services.spec.js @@ -78,7 +78,6 @@ describe('Ticket services path', () => { it('should create a new service type then add price then create the service', async() => { await page.write(selectors.ticketService.newServiceTypeName, 'Documentos'); - await page.autocompleteSearch(selectors.ticketService.newServiceTypeExpense, 'Retencion'); await page.waitToClick(selectors.ticketService.saveServiceTypeButton); await page.write(selectors.ticketService.firstPrice, '999'); await page.waitToClick(selectors.ticketService.saveServiceButton); @@ -109,13 +108,6 @@ describe('Ticket services path', () => { expect(result).toEqual('999'); }); - it('should confirm the service VAT was created correctly', async() => { - const result = await page - .waitToGetProperty(selectors.ticketService.firstVatType, 'value'); - - expect(result).toEqual('General VAT'); - }); - it('should delete the service', async() => { await page.waitToClick(selectors.ticketService.fistDeleteServiceButton); await page.waitForNumberOfElements(selectors.ticketService.serviceLine, 0); diff --git a/modules/ticket/back/models/ticket-service-type.json b/modules/ticket/back/models/ticket-service-type.json index 9912c7952..623d0f398 100644 --- a/modules/ticket/back/models/ticket-service-type.json +++ b/modules/ticket/back/models/ticket-service-type.json @@ -17,7 +17,6 @@ }, "expenseFk": { "type": "Number", - "required": true, "mysql": { "columnName": "expenceFk" } diff --git a/modules/ticket/front/services/index.html b/modules/ticket/front/services/index.html index 261b50d6f..65d473013 100644 --- a/modules/ticket/front/services/index.html +++ b/modules/ticket/front/services/index.html @@ -41,13 +41,6 @@ ng-model="service.price" step="0.01"> - - - - - - From b7721719ca6ec0e572c58ff00330e8ecb817be8f Mon Sep 17 00:00:00 2001 From: jgallego Date: Mon, 21 Sep 2020 11:07:10 +0200 Subject: [PATCH 02/18] test arreglados --- e2e/helpers/selectors.js | 2 +- e2e/paths/04-item/02_basic_data.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 8f66a3689..7e8c80424 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -276,7 +276,7 @@ export default { relevancy: 'vn-item-basic-data vn-input-number[ng-model="$ctrl.item.relevancy"]', origin: 'vn-autocomplete[ng-model="$ctrl.item.originFk"]', compression: 'vn-item-basic-data vn-input-number[ng-model="$ctrl.item.compression"]', - isFragile: 'vn-check[label="isFragile"]', + isFragile: 'vn-check[label="Fragile"]', longName: 'vn-textfield[ng-model="$ctrl.item.longName"]', isActiveCheckbox: 'vn-check[label="Active"]', priceInKgCheckbox: 'vn-check[label="Price in kg"]', diff --git a/e2e/paths/04-item/02_basic_data.spec.js b/e2e/paths/04-item/02_basic_data.spec.js index 836efaa2e..f04031480 100644 --- a/e2e/paths/04-item/02_basic_data.spec.js +++ b/e2e/paths/04-item/02_basic_data.spec.js @@ -113,7 +113,7 @@ describe('Item Edit basic data path', () => { const result = await page .checkboxState(selectors.itemBasicData.isFragile); - expect(result).toBe('unchecked'); + expect(result).toBe('checked'); }); it('should confirm isActive checkbox is unchecked', async() => { From 58965a968772fe57cd5b1500cbcdb50846b4c9b4 Mon Sep 17 00:00:00 2001 From: joan Date: Wed, 30 Sep 2020 07:38:43 +0200 Subject: [PATCH 03/18] Enabled loggable on calendar model --- modules/worker/back/models/calendar.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/modules/worker/back/models/calendar.json b/modules/worker/back/models/calendar.json index 417442571..199d81e6c 100644 --- a/modules/worker/back/models/calendar.json +++ b/modules/worker/back/models/calendar.json @@ -1,6 +1,10 @@ { "name": "Calendar", - "base": "VnModel", + "base": "Loggable", + "log": { + "model": "WorkerLog", + "relation": "labour" + }, "options": { "mysql": { "table": "calendar" @@ -23,6 +27,11 @@ "type": "belongsTo", "model": "AbsenceType", "foreignKey": "dayOffTypeFk" + }, + "labour": { + "type": "belongsTo", + "model": "WorkerLabour", + "foreignKey": "businessFk" } } } From 891a113326d471672243b229b65ba1d83a45452a Mon Sep 17 00:00:00 2001 From: jgallego Date: Wed, 30 Sep 2020 14:07:34 +0200 Subject: [PATCH 04/18] package --- package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f0ae74065..411a06a7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6916,9 +6916,9 @@ "dev": true }, "bl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz", - "integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", "requires": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" @@ -13541,7 +13541,7 @@ "jasmine-spec-reporter": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz", - "integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==", + "integrity": "sha1-HWMq7ANBZwrTJPkrqEtLMrNeniI=", "dev": true, "requires": { "colors": "1.1.2" From 78e22df1774e9b10526d74eacc976f2afe6241bc Mon Sep 17 00:00:00 2001 From: jgallego Date: Thu, 1 Oct 2020 16:45:28 +0200 Subject: [PATCH 05/18] test e2e de expense ok --- db/dump/fixtures.sql | 4 ++- e2e/paths/04-item/09_regularize.spec.js | 2 +- package-lock.json | 44 ++++++++++++------------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index f2267f4b8..ac0386876 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -479,7 +479,9 @@ INSERT INTO `vn`.`expence`(`id`, `taxTypeFk`, `name`, `isWithheld`) (4751000000, 1, 'Retenciones', 1), (4751000000, 6, 'Retencion', 0), (6210000567, 0, 'Alquiler VNH', 0), - (7001000000, 1, 'Mercaderia', 0); + (7001000000, 1, 'Mercaderia', 0), + (7050000000, 1, 'Prestacion de servicios', 1); + INSERT INTO `vn`.`invoiceOutExpence`(`id`, `invoiceOutFk`, `amount`, `expenceFk`, `created`) VALUES diff --git a/e2e/paths/04-item/09_regularize.spec.js b/e2e/paths/04-item/09_regularize.spec.js index 6de995515..822a4188d 100644 --- a/e2e/paths/04-item/09_regularize.spec.js +++ b/e2e/paths/04-item/09_regularize.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -describe('Item regularize path', () => { +fdescribe('Item regularize path', () => { let browser; let page; beforeAll(async() => { diff --git a/package-lock.json b/package-lock.json index 72edc22a3..944d41637 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5835,7 +5835,7 @@ }, "util": { "version": "0.10.3", - "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -6806,7 +6806,7 @@ "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { "cache-base": "^1.0.1", @@ -7329,7 +7329,7 @@ "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { "collection-visit": "^1.0.0", @@ -7543,7 +7543,7 @@ "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { "arr-union": "^3.1.0", @@ -9796,7 +9796,7 @@ }, "file-loader": { "version": "1.1.11", - "resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "dev": true, "requires": { @@ -10982,7 +10982,7 @@ "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { "global-prefix": "^1.0.1", @@ -13207,7 +13207,7 @@ "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "requires": { "isobject": "^3.0.1" @@ -22227,7 +22227,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } @@ -22620,7 +22620,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -22834,7 +22834,7 @@ "dependencies": { "source-map": { "version": "0.4.4", - "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { @@ -22850,18 +22850,18 @@ "dev": true }, "selfsigned": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz", - "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==", + "version": "1.10.8", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", + "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", "dev": true, "requires": { - "node-forge": "0.9.0" + "node-forge": "^0.10.0" }, "dependencies": { "node-forge": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", - "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", "dev": true } } @@ -23295,7 +23295,7 @@ "snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { "define-property": "^1.0.0", @@ -23346,7 +23346,7 @@ "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { "kind-of": "^3.2.0" @@ -23630,7 +23630,7 @@ "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { "extend-shallow": "^3.0.0" @@ -24941,7 +24941,7 @@ "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "integrity": "sha1-/jZfX3XsntTlaCXgu3bSSrdK+Ds=", "dev": true, "requires": { "nopt": "~1.0.10" @@ -26733,7 +26733,7 @@ }, "xmlbuilder": { "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" }, "xmlchars": { From 8b4d25d506f5d9f6404f94d949e79dc38a3046e1 Mon Sep 17 00:00:00 2001 From: jgallego Date: Fri, 2 Oct 2020 08:57:51 +0200 Subject: [PATCH 06/18] test arreglados windows --- e2e/paths/04-item/09_regularize.spec.js | 2 +- e2e/paths/05-ticket/14_create_ticket.spec.js | 1 + e2e/paths/12-entry/04_create.spec.js | 7 +++---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/e2e/paths/04-item/09_regularize.spec.js b/e2e/paths/04-item/09_regularize.spec.js index 6b39ed361..fdb1e0184 100644 --- a/e2e/paths/04-item/09_regularize.spec.js +++ b/e2e/paths/04-item/09_regularize.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -fdescribe('Item regularize path', () => { +describe('Item regularize path', () => { let browser; let page; beforeAll(async() => { diff --git a/e2e/paths/05-ticket/14_create_ticket.spec.js b/e2e/paths/05-ticket/14_create_ticket.spec.js index 26c22ad3d..496cac161 100644 --- a/e2e/paths/05-ticket/14_create_ticket.spec.js +++ b/e2e/paths/05-ticket/14_create_ticket.spec.js @@ -42,6 +42,7 @@ describe('Ticket create path', () => { it('should again open the new ticket form', async() => { await page.waitToClick(selectors.globalItems.returnToModuleIndexButton); + await page.waitFor(500); await page.waitToClick(selectors.ticketsIndex.newTicketButton); await page.waitForState('ticket.create'); }); diff --git a/e2e/paths/12-entry/04_create.spec.js b/e2e/paths/12-entry/04_create.spec.js index 90dac618a..8cf23813b 100644 --- a/e2e/paths/12-entry/04_create.spec.js +++ b/e2e/paths/12-entry/04_create.spec.js @@ -20,14 +20,13 @@ describe('Entry create path', () => { await page.waitForState('entry.create'); }); - it('should fill the form to create a valid entry', async() => { + it('should fill the form to create a valid entry then redirect to basic Data', async() => { await page.autocompleteSearch(selectors.entryIndex.newEntrySupplier, '2'); await page.autocompleteSearch(selectors.entryIndex.newEntryTravel, 'Warehouse Three'); await page.autocompleteSearch(selectors.entryIndex.newEntryCompany, 'ORN'); - await page.waitToClick(selectors.entryIndex.saveNewEntry); - }); - it('should be redirected to entry basic data', async() => { + await page.waitToClick(selectors.entryIndex.saveNewEntry); + await page.waitFor(500); await page.waitForState('entry.card.basicData'); }); }); From 420dfdbdff698d24023e32569d20f4a6d6e2c83b Mon Sep 17 00:00:00 2001 From: joan Date: Fri, 2 Oct 2020 12:23:48 +0200 Subject: [PATCH 07/18] Send notification by email --- db/changes/10230-a/00-ACL.sql | 1 + db/changes/10230-a/00-department.sql | 4 ++ db/dump/fixtures.sql | 8 +++- loopback/locale/en.json | 4 +- loopback/locale/es.json | 5 ++- .../back/methods/worker/createAbsence.js | 36 +++++++++++++++- .../back/methods/worker/deleteAbsence.js | 43 ++++++++++++++++++- .../worker/specs/createAbsence.spec.js | 20 +++++++-- .../worker/specs/deleteAbsence.spec.js | 21 +++++++-- modules/worker/back/models/department.json | 3 ++ modules/worker/front/routes.json | 2 +- 11 files changed, 131 insertions(+), 16 deletions(-) create mode 100644 db/changes/10230-a/00-ACL.sql create mode 100644 db/changes/10230-a/00-department.sql diff --git a/db/changes/10230-a/00-ACL.sql b/db/changes/10230-a/00-ACL.sql new file mode 100644 index 000000000..0e5c9e1dc --- /dev/null +++ b/db/changes/10230-a/00-ACL.sql @@ -0,0 +1 @@ +UPDATE salix.ACL t SET t.principalId = 'salesAssistant' WHERE t.id = 234 \ No newline at end of file diff --git a/db/changes/10230-a/00-department.sql b/db/changes/10230-a/00-department.sql new file mode 100644 index 000000000..d08063356 --- /dev/null +++ b/db/changes/10230-a/00-department.sql @@ -0,0 +1,4 @@ +ALTER TABLE `vn`.department + ADD notificationEmail VARCHAR(150) null; + +UPDATE vn.department t SET t.notificationEmail = 'joan@verdnatura.es' WHERE t.id = 43 \ No newline at end of file diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index f2267f4b8..7ff5792e6 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -42,8 +42,8 @@ INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `userFk`, `bossF FROM `vn`.`user`; UPDATE `vn`.`worker` SET bossFk = NULL WHERE id = 20; -UPDATE `vn`.`worker` SET bossFk = 20 - WHERE id = 1 OR id = 9; +UPDATE `vn`.`worker` SET bossFk = 20 WHERE id = 1 OR id = 9; +UPDATE `vn`.`worker` SET bossFk = 19 WHERE id = 18; DELETE FROM `vn`.`worker` WHERE firstName ='customer'; @@ -1694,6 +1694,10 @@ UPDATE `postgresql`.`business_labour` bl SET bl.`professional_category_id` = 31 WHERE p.`Id_trabajador` = 110; +UPDATE `postgresql`.`business_labour` bl + SET bl.`department_id` = 43 +WHERE business_id IN(18, 19); + INSERT INTO `postgresql`.`media`(`media_id`, `media_type_id`, `value`, `sort`) VALUES (1, 10, 600123321, 0), diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 114b07edf..4a970190d 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -68,5 +68,7 @@ "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}}", "Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment", - "NOT_ZONE_WITH_THIS_PARAMETERS": "NOT_ZONE_WITH_THIS_PARAMETERS" + "NOT_ZONE_WITH_THIS_PARAMETERS": "NOT_ZONE_WITH_THIS_PARAMETERS", + "Created absence": "The worker {{author}} has added an absence of type '{{absenceType}}' to {{employee}} for day {{dated}}.", + "Deleted absence": "The worker {{author}} has deleted an absence of type '{{absenceType}}' to {{employee}} for day {{dated}}." } \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index ea5a09952..1f536c3ce 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -143,5 +143,8 @@ "Role name must be written in camelCase": "Role name must be written in camelCase", "can't be set": "can't be set", "Email already exists": "Email already exists", - "User already exists": "User already exists" + "User already exists": "User already exists", + "Absence change notification on the labour calendar": "Notificacion de cambio de ausencia en el calendario laboral", + "Created absence": "El empleado {{author}} ha añadido una ausencia de tipo '{{absenceType}}' a {{employee}} para el día {{dated}}.", + "Deleted absence": "El empleado {{author}} ha eliminado una ausencia de tipo '{{absenceType}}' a {{employee}} del día {{dated}}." } \ No newline at end of file diff --git a/modules/worker/back/methods/worker/createAbsence.js b/modules/worker/back/methods/worker/createAbsence.js index 3163e697d..cc0ee13a6 100644 --- a/modules/worker/back/methods/worker/createAbsence.js +++ b/modules/worker/back/methods/worker/createAbsence.js @@ -31,6 +31,7 @@ module.exports = Self => { Self.createAbsence = async(ctx, id, absenceTypeId, dated) => { const models = Self.app.models; + const $t = ctx.req.__; // $translate const userId = ctx.req.accessToken.userId; const isSubordinate = await models.Worker.isSubordinate(ctx, id); const isTeamBoss = await models.Account.hasRole(userId, 'teamBoss'); @@ -39,6 +40,7 @@ module.exports = Self => { throw new UserError(`You don't have enough privileges`); const labour = await models.WorkerLabour.findOne({ + include: {relation: 'department'}, where: { and: [ {workerFk: id}, @@ -49,10 +51,42 @@ module.exports = Self => { } }); - return models.Calendar.create({ + const absence = await models.Calendar.create({ businessFk: labour.businessFk, dayOffTypeFk: absenceTypeId, dated: dated }); + + const department = labour.department(); + if (department && department.notificationEmail) { + const absenceType = await models.AbsenceType.findById(absenceTypeId); + const account = await models.Account.findById(userId); + const subordinated = await models.Account.findById(id); + const origin = ctx.req.headers.origin; + const body = $t('Created absence', { + author: account.nickname, + employee: subordinated.nickname, + absenceType: absenceType.name, + dated: formatDate(dated), + workerUrl: `${origin}/#!/worker/${id}/calendar` + }); + await models.Mail.create({ + subject: $t('Absence change notification on the labour calendar'), + body: body, + sender: department.notificationEmail + }); + } + + return absence; }; + + function formatDate(date) { + let day = date.getDate(); + if (day < 10) day = `0${day}`; + let month = date.getMonth(); + if (month < 10) month = `0${month}`; + let year = date.getFullYear(); + + return `${day}-${month}-${year}`; + } }; diff --git a/modules/worker/back/methods/worker/deleteAbsence.js b/modules/worker/back/methods/worker/deleteAbsence.js index 0fe8f7dc8..c7e24fa58 100644 --- a/modules/worker/back/methods/worker/deleteAbsence.js +++ b/modules/worker/back/methods/worker/deleteAbsence.js @@ -23,6 +23,7 @@ module.exports = Self => { Self.deleteAbsence = async(ctx, id, absenceId) => { const models = Self.app.models; + const $t = ctx.req.__; // $translate const userId = ctx.req.accessToken.userId; const isSubordinate = await models.Worker.isSubordinate(ctx, id); const isTeamBoss = await models.Account.hasRole(userId, 'teamBoss'); @@ -30,8 +31,46 @@ module.exports = Self => { if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss)) throw new UserError(`You don't have enough privileges`); - const absence = await models.Calendar.findById(absenceId); + const absence = await models.Calendar.findById(absenceId, { + include: { + relation: 'labour', + scope: { + include: {relation: 'department'} + } + } + }); + const result = await absence.destroy(); + const labour = absence.labour(); + const department = labour && labour.department(); + if (department && department.notificationEmail) { + const absenceType = await models.AbsenceType.findById(absence.dayOffTypeFk); + const account = await models.Account.findById(userId); + const subordinated = await models.Account.findById(labour.workerFk); + const origin = ctx.req.headers.origin; + const body = $t('Deleted absence', { + author: account.nickname, + employee: subordinated.nickname, + absenceType: absenceType.name, + dated: formatDate(absence.dated), + workerUrl: `${origin}/#!/worker/${id}/calendar` + }); + await models.Mail.create({ + subject: $t('Absence change notification on the labour calendar'), + body: body, + sender: department.notificationEmail + }); + } - return absence.destroy(); + return result; }; + + function formatDate(date) { + let day = date.getDate(); + if (day < 10) day = `0${day}`; + let month = date.getMonth(); + if (month < 10) month = `0${month}`; + let year = date.getFullYear(); + + return `${day}-${month}-${year}`; + } }; diff --git a/modules/worker/back/methods/worker/specs/createAbsence.spec.js b/modules/worker/back/methods/worker/specs/createAbsence.spec.js index df48cf80b..324dab99d 100644 --- a/modules/worker/back/methods/worker/specs/createAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/createAbsence.spec.js @@ -1,7 +1,8 @@ const app = require('vn-loopback/server/server'); +const LoopBackContext = require('loopback-context'); describe('Worker createAbsence()', () => { - const workerId = 106; + const workerId = 18; let createdAbsence; afterAll(async() => { @@ -10,7 +11,7 @@ describe('Worker createAbsence()', () => { }); it('should return an error for a user without enough privileges', async() => { - const ctx = {req: {accessToken: {userId: 106}}}; + const ctx = {req: {accessToken: {userId: 18}}}; const absenceTypeId = 1; const dated = new Date(); @@ -25,12 +26,23 @@ describe('Worker createAbsence()', () => { }); it('should create a new absence', async() => { - const ctx = {req: {accessToken: {userId: 37}}}; + const activeCtx = { + accessToken: {userId: 19}, + headers: {origin: 'http://localhost'} + }; + const ctx = {req: activeCtx}; + ctx.req.__ = value => { + return value; + }; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + const absenceTypeId = 1; const dated = new Date(); createdAbsence = await app.models.Worker.createAbsence(ctx, workerId, absenceTypeId, dated); - const expectedBusinessId = 106; + const expectedBusinessId = 18; const expectedAbsenceTypeId = 1; expect(createdAbsence.businessFk).toEqual(expectedBusinessId); diff --git a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js index 140edada8..c53bc607e 100644 --- a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js @@ -1,11 +1,22 @@ const app = require('vn-loopback/server/server'); +const LoopBackContext = require('loopback-context'); -describe('Worker deleteAbsence()', () => { - const workerId = 106; +fdescribe('Worker deleteAbsence()', () => { + const workerId = 18; let createdAbsence; + const activeCtx = { + accessToken: {userId: 19}, + headers: {origin: 'http://localhost'} + }; + const ctx = {req: activeCtx}; + ctx.req.__ = value => { + return value; + }; it('should return an error for a user without enough privileges', async() => { - const ctx = {req: {accessToken: {userId: 106}}}; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); const businessId = 106; createdAbsence = await app.models.Calendar.create({ businessFk: businessId, @@ -24,7 +35,9 @@ describe('Worker deleteAbsence()', () => { }); it('should create a new absence', async() => { - const ctx = {req: {accessToken: {userId: 37}}}; + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); const businessId = 106; expect(createdAbsence.businessFk).toEqual(businessId); diff --git a/modules/worker/back/models/department.json b/modules/worker/back/models/department.json index d8ec7313a..31ebbb09a 100644 --- a/modules/worker/back/models/department.json +++ b/modules/worker/back/models/department.json @@ -28,6 +28,9 @@ }, "chatName": { "type": "String" + }, + "notificationEmail": { + "type": "String" } } } diff --git a/modules/worker/front/routes.json b/modules/worker/front/routes.json index 7825e9735..9ab2f597e 100644 --- a/modules/worker/front/routes.json +++ b/modules/worker/front/routes.json @@ -63,7 +63,7 @@ "state": "worker.card.workerLog", "component": "vn-worker-log", "description": "Log", - "acl": ["hr"] + "acl": ["salesAssistant"] }, { "url": "/pbx", "state": "worker.card.pbx", From cdde4d95d77455c7668dbb636963aaa121dafe45 Mon Sep 17 00:00:00 2001 From: joan Date: Mon, 5 Oct 2020 07:53:03 +0200 Subject: [PATCH 08/18] Added filter --- back/methods/campaign/latest.js | 41 +++++++++++++++++++ back/methods/campaign/upcoming.js | 30 ++++++++++++++ back/model-config.json | 3 ++ back/models/campaign.js | 4 ++ back/models/campaign.json | 33 +++++++++++++++ db/changes/10230-oktoberFest/00-campaign.sql | 37 +++++++++++++++++ front/core/components/autocomplete/index.js | 24 +++++++++-- .../front/consumption-search-panel/index.html | 16 ++++++++ .../front/consumption-search-panel/index.js | 31 +++++++++++++- .../consumption-search-panel/locale/en.yml | 3 ++ .../consumption-search-panel/locale/es.yml | 6 ++- 11 files changed, 223 insertions(+), 5 deletions(-) create mode 100644 back/methods/campaign/latest.js create mode 100644 back/methods/campaign/upcoming.js create mode 100644 back/models/campaign.js create mode 100644 back/models/campaign.json create mode 100644 db/changes/10230-oktoberFest/00-campaign.sql create mode 100644 modules/client/front/consumption-search-panel/locale/en.yml diff --git a/back/methods/campaign/latest.js b/back/methods/campaign/latest.js new file mode 100644 index 000000000..f1449dfec --- /dev/null +++ b/back/methods/campaign/latest.js @@ -0,0 +1,41 @@ +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const mergeFilters = require('vn-loopback/util/filter').mergeFilters; + +module.exports = Self => { + Self.remoteMethod('latest', { + description: 'Returns the lastest campaigns', + accessType: 'READ', + accepts: [{ + arg: 'filter', + type: 'Object', + description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string` + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/latest`, + verb: 'GET' + } + }); + + Self.latest = async filter => { + const conn = Self.dataSource.connector; + const minDate = new Date(); + minDate.setFullYear(minDate.getFullYear() - 1); + minDate.setMonth(0); + minDate.setDate(1); + + const where = {dated: {gte: minDate}}; + filter = mergeFilters(filter, {where}); + + const stmt = new ParameterizedSQL( + `SELECT * FROM campaign`); + stmt.merge(conn.makeWhere(filter.where)); + stmt.merge('GROUP BY code'); + stmt.merge(conn.makePagination(filter)); + + return conn.executeStmt(stmt); + }; +}; diff --git a/back/methods/campaign/upcoming.js b/back/methods/campaign/upcoming.js new file mode 100644 index 000000000..cc9f7f910 --- /dev/null +++ b/back/methods/campaign/upcoming.js @@ -0,0 +1,30 @@ +module.exports = Self => { + Self.remoteMethod('upcoming', { + description: 'Returns the lastest campaigns', + accessType: 'READ', + accepts: [], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/upcoming`, + verb: 'GET' + } + }); + + Self.upcoming = async() => { + const minDate = new Date(); + minDate.setMonth(0); + minDate.setDate(1); + + return Self.findOne({ + where: { + dated: { + lt: minDate + } + }, + order: 'dated DESC' + }); + }; +}; diff --git a/back/model-config.json b/back/model-config.json index b8a8f04ac..7a59aaf9a 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -8,6 +8,9 @@ "Bank": { "dataSource": "vn" }, + "Campaign": { + "dataSource": "vn" + }, "Country": { "dataSource": "vn" }, diff --git a/back/models/campaign.js b/back/models/campaign.js new file mode 100644 index 000000000..db5f2e828 --- /dev/null +++ b/back/models/campaign.js @@ -0,0 +1,4 @@ +module.exports = Self => { + require('../methods/campaign/latest')(Self); + require('../methods/campaign/upcoming')(Self); +}; diff --git a/back/models/campaign.json b/back/models/campaign.json new file mode 100644 index 000000000..e99e8d819 --- /dev/null +++ b/back/models/campaign.json @@ -0,0 +1,33 @@ +{ + "name": "Campaign", + "base": "VnModel", + "options": { + "mysql": { + "table": "campaign" + } + }, + "properties": { + "id": { + "type": "number", + "required": true + }, + "code": { + "type": "string", + "required": true + }, + "dated": { + "type": "date" + }, + "scopeDays": { + "type": "number" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} diff --git a/db/changes/10230-oktoberFest/00-campaign.sql b/db/changes/10230-oktoberFest/00-campaign.sql new file mode 100644 index 000000000..0e5b91170 --- /dev/null +++ b/db/changes/10230-oktoberFest/00-campaign.sql @@ -0,0 +1,37 @@ +CREATE TABLE `vn`.campaign +( + id INT AUTO_INCREMENT, + code ENUM('mothersDay', 'allSaints', 'valentinesDay') NOT NULL, + dated DATE DEFAULT CURDATE() NOT NULL, + scopeDays INT NOT NULL DEFAULT '15', + CONSTRAINT campaign_pk + PRIMARY KEY (id) +); + +CREATE UNIQUE INDEX campaign_dated_uindex + ON `vn`.campaign (dated); + +-- TODOS SANTOS +INSERT INTO `vn`.campaign(code, dated) +SELECT 'allSaints' AS code, dated + FROM `vn`.time +WHERE dated >= CONCAT(YEAR(CURDATE()) - 1, '-01-01') + AND month = 11 + AND day = 1; + +-- SAN VALENTIN +INSERT INTO `vn`.campaign(code, dated) +SELECT 'valentinesDay' AS code, dated + FROM `vn`.time +WHERE dated >= CONCAT(YEAR(CURDATE()) - 1, '-01-01') + AND month = 2 + AND day = 14; + +-- DIA DE LA MADRE +INSERT INTO `vn`.campaign(code, dated) +SELECT 'mothersDay' AS code, dated + FROM `vn`.time +WHERE dated >= CONCAT(YEAR(CURDATE()) - 1, '-01-01') + AND month = 5 + AND WEEK(dated, 5) - WEEK(DATE_SUB(dated, INTERVAL DAYOFMONTH(dated) - 1 DAY), 5) + 1 = 1 -- WEEK OF MONTH + AND DAYOFWEEK(dated) = 1; diff --git a/front/core/components/autocomplete/index.js b/front/core/components/autocomplete/index.js index b335d266f..742ad6f2a 100755 --- a/front/core/components/autocomplete/index.js +++ b/front/core/components/autocomplete/index.js @@ -190,9 +190,27 @@ export default class Autocomplete extends Field { this.input.value = display; - if (this.translateFields) { - if (this.translateFields.indexOf(this.showField) > -1) - this.input.value = this.$t(display); + if (this.translateFields && this.selection) { + const translations = []; + for (let field of this.translateFields) { + const fieldValue = this._selection[field]; + translations.push({ + original: fieldValue, + value: this.$t(fieldValue) + }); + } + + for (let translation of translations) { + const orgValue = translation.original; + const value = translation.value; + + display = display.replace(orgValue, value); + } + + this.input.value = display; + + /* if (this.translateFields.indexOf(this.showField) > -1) + this.input.value = this.$t(display); */ } } diff --git a/modules/client/front/consumption-search-panel/index.html b/modules/client/front/consumption-search-panel/index.html index e957c891b..0edb0b34a 100644 --- a/modules/client/front/consumption-search-panel/index.html +++ b/modules/client/front/consumption-search-panel/index.html @@ -49,6 +49,22 @@ ng-model="filter.categoryId"> + + + + {{code}} {{dated | date: 'yyyy'}} + + + { + const filter = this.$.filter; + filter.campaign = res.data.id; + console.log(res.data); + }); + } + + get campaignSelection() { + return this._campaignSelection; + } + + set campaignSelection(value) { + this._campaignSelection = value; + + if (!value) return; + + const filter = this.$.filter; + const from = new Date(value.dated); + from.setDate(from.getDate() - value.scopeDays); + + filter.to = value.dated; + filter.from = from; + } +} + ngModule.vnComponent('vnConsumptionSearchPanel', { template: require('./index.html'), - controller: SearchPanel + controller: Controller }); diff --git a/modules/client/front/consumption-search-panel/locale/en.yml b/modules/client/front/consumption-search-panel/locale/en.yml new file mode 100644 index 000000000..03364d7cf --- /dev/null +++ b/modules/client/front/consumption-search-panel/locale/en.yml @@ -0,0 +1,3 @@ +allSaints: All Saints Day +valentinesDay: Valentine's Day +mothersDay: Mother's day \ No newline at end of file diff --git a/modules/client/front/consumption-search-panel/locale/es.yml b/modules/client/front/consumption-search-panel/locale/es.yml index 68de42b23..f136283f8 100644 --- a/modules/client/front/consumption-search-panel/locale/es.yml +++ b/modules/client/front/consumption-search-panel/locale/es.yml @@ -1,3 +1,7 @@ Item id: Id artículo From: Desde -To: Hasta \ No newline at end of file +To: Hasta +Campaign: Campaña +allSaints: Día de todos los Santos +valentinesDay: Día de San Valentín +mothersDay: Día de la madre \ No newline at end of file From e3b14405b71ab749bdd91ea90d10898fe85792ff Mon Sep 17 00:00:00 2001 From: joan Date: Mon, 5 Oct 2020 08:50:07 +0200 Subject: [PATCH 09/18] Added unit tests --- back/methods/campaign/spec/latest.spec.js | 18 +++++++++++ back/methods/campaign/spec/upcoming.spec.js | 16 ++++++++++ .../front/consumption-search-panel/index.js | 5 ++- .../consumption-search-panel/index.spec.js | 31 +++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 back/methods/campaign/spec/latest.spec.js create mode 100644 back/methods/campaign/spec/upcoming.spec.js create mode 100644 modules/client/front/consumption-search-panel/index.spec.js diff --git a/back/methods/campaign/spec/latest.spec.js b/back/methods/campaign/spec/latest.spec.js new file mode 100644 index 000000000..c76231ab2 --- /dev/null +++ b/back/methods/campaign/spec/latest.spec.js @@ -0,0 +1,18 @@ +const app = require('vn-loopback/server/server'); + +describe('campaign latest()', () => { + it('should return the campaigns from the last year', async() => { + let response = await app.models.Campaign.latest(); + + const lastYearDate = new Date(); + lastYearDate.setFullYear(lastYearDate.getFullYear() - 1); + const lastYear = lastYearDate.getFullYear(); + + const randomIndex = Math.floor(Math.random() * 3); + const campaignDated = response[randomIndex].dated; + const campaignYear = campaignDated.getFullYear(); + + expect(response.length).toEqual(3); + expect(campaignYear).toEqual(lastYear); + }); +}); diff --git a/back/methods/campaign/spec/upcoming.spec.js b/back/methods/campaign/spec/upcoming.spec.js new file mode 100644 index 000000000..953683e7a --- /dev/null +++ b/back/methods/campaign/spec/upcoming.spec.js @@ -0,0 +1,16 @@ +const app = require('vn-loopback/server/server'); + +describe('campaign upcoming()', () => { + it('should return the upcoming campaign but from the last year', async() => { + let response = await app.models.Campaign.upcoming(); + + const lastYearDate = new Date(); + lastYearDate.setFullYear(lastYearDate.getFullYear() - 1); + const lastYear = lastYearDate.getFullYear(); + + const campaignDated = response.dated; + const campaignYear = campaignDated.getFullYear(); + + expect(campaignYear).toEqual(lastYear); + }); +}); diff --git a/modules/client/front/consumption-search-panel/index.js b/modules/client/front/consumption-search-panel/index.js index 53596c8f3..099564efc 100644 --- a/modules/client/front/consumption-search-panel/index.js +++ b/modules/client/front/consumption-search-panel/index.js @@ -5,10 +5,13 @@ class Controller extends SearchPanel { constructor($, $element) { super($, $element); + this.getUpcomingCampaing(); + } + + getUpcomingCampaing() { this.$http.get('Campaigns/upcoming').then(res => { const filter = this.$.filter; filter.campaign = res.data.id; - console.log(res.data); }); } diff --git a/modules/client/front/consumption-search-panel/index.spec.js b/modules/client/front/consumption-search-panel/index.spec.js new file mode 100644 index 000000000..dfab07086 --- /dev/null +++ b/modules/client/front/consumption-search-panel/index.spec.js @@ -0,0 +1,31 @@ +import './index.js'; + +describe('Client', () => { + describe('Component vnConsumptionSearchPanel', () => { + let $httpBackend; + let $element; + let controller; + + beforeEach(ngModule('client')); + + beforeEach(inject(($componentController, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + $element = angular.element(`
`); + controller = $componentController('vnConsumptionSearchPanel', {$element}); + controller.$.filter = {}; + $httpBackend.expect('GET', 'Campaigns/upcoming').respond(200, {id: 1}); + })); + + describe('getUpcomingCampaing()', () => { + it(`should make an HTTP GET query`, () => { + $httpBackend.expect('GET', 'Campaigns/upcoming').respond(200, {id: 2, code: 'allSaints'}); + controller.getUpcomingCampaing(); + $httpBackend.flush(); + + const filter = controller.$.filter; + + expect(filter.campaign).toEqual(2); + }); + }); + }); +}); From e95514d96741b94e3a4d4d06128c0431ea7aabb5 Mon Sep 17 00:00:00 2001 From: jgallego Date: Mon, 5 Oct 2020 09:24:49 +0200 Subject: [PATCH 10/18] reorganiza campos --- modules/entry/front/basic-data/index.html | 48 +++++++++++------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/modules/entry/front/basic-data/index.html b/modules/entry/front/basic-data/index.html index 67ac18df5..f3adc6b02 100644 --- a/modules/entry/front/basic-data/index.html +++ b/modules/entry/front/basic-data/index.html @@ -9,30 +9,6 @@
- - - - - - - - - - + + + + + + + + + + Date: Mon, 5 Oct 2020 10:09:36 +0200 Subject: [PATCH 11/18] Updated unit test --- .../back/methods/worker/specs/deleteAbsence.spec.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js index c53bc607e..2f72a8435 100644 --- a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js @@ -1,7 +1,7 @@ const app = require('vn-loopback/server/server'); const LoopBackContext = require('loopback-context'); -fdescribe('Worker deleteAbsence()', () => { +describe('Worker deleteAbsence()', () => { const workerId = 18; let createdAbsence; const activeCtx = { @@ -17,7 +17,9 @@ fdescribe('Worker deleteAbsence()', () => { spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ active: activeCtx }); - const businessId = 106; + + activeCtx.accessToken.userId = 106; + const businessId = 18; createdAbsence = await app.models.Calendar.create({ businessFk: businessId, dayOffTypeFk: 1, @@ -25,7 +27,7 @@ fdescribe('Worker deleteAbsence()', () => { }); let error; - await app.models.Worker.deleteAbsence(ctx, workerId, createdAbsence.id).catch(e => { + await app.models.Worker.deleteAbsence(ctx, 18, createdAbsence.id).catch(e => { error = e; }).finally(() => { expect(error.message).toEqual(`You don't have enough privileges`); @@ -38,7 +40,9 @@ fdescribe('Worker deleteAbsence()', () => { spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ active: activeCtx }); - const businessId = 106; + + activeCtx.accessToken.userId = 19; + const businessId = 18; expect(createdAbsence.businessFk).toEqual(businessId); From cef2dc982fd5115e1d208cfc76e3a7e2cdaa15f5 Mon Sep 17 00:00:00 2001 From: joan Date: Mon, 5 Oct 2020 10:47:12 +0200 Subject: [PATCH 12/18] Updated sql --- db/changes/10230-a/00-department.sql | 4 ---- db/changes/{10230-a => 10230-oktoberFest}/00-ACL.sql | 0 db/changes/10230-oktoberFest/00-department.sql | 4 ++++ 3 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 db/changes/10230-a/00-department.sql rename db/changes/{10230-a => 10230-oktoberFest}/00-ACL.sql (100%) create mode 100644 db/changes/10230-oktoberFest/00-department.sql diff --git a/db/changes/10230-a/00-department.sql b/db/changes/10230-a/00-department.sql deleted file mode 100644 index d08063356..000000000 --- a/db/changes/10230-a/00-department.sql +++ /dev/null @@ -1,4 +0,0 @@ -ALTER TABLE `vn`.department - ADD notificationEmail VARCHAR(150) null; - -UPDATE vn.department t SET t.notificationEmail = 'joan@verdnatura.es' WHERE t.id = 43 \ No newline at end of file diff --git a/db/changes/10230-a/00-ACL.sql b/db/changes/10230-oktoberFest/00-ACL.sql similarity index 100% rename from db/changes/10230-a/00-ACL.sql rename to db/changes/10230-oktoberFest/00-ACL.sql diff --git a/db/changes/10230-oktoberFest/00-department.sql b/db/changes/10230-oktoberFest/00-department.sql new file mode 100644 index 000000000..38d4f6875 --- /dev/null +++ b/db/changes/10230-oktoberFest/00-department.sql @@ -0,0 +1,4 @@ +ALTER TABLE `vn`.department + ADD notificationEmail VARCHAR(150) null; + +UPDATE vn.department t SET t.notificationEmail = 'direccioncomercial@verdnatura.es' WHERE t.id = 43 \ No newline at end of file From 531bb6da25901aab291f3d4f7d04defec9f4aa27 Mon Sep 17 00:00:00 2001 From: jgallego Date: Mon, 5 Oct 2020 13:22:56 +0200 Subject: [PATCH 13/18] quito copy --- .../10220-back2school/{00-entryLog copy.sql => 00-entryLog.sql} | 1 + 1 file changed, 1 insertion(+) rename db/changes/10220-back2school/{00-entryLog copy.sql => 00-entryLog.sql} (99%) diff --git a/db/changes/10220-back2school/00-entryLog copy.sql b/db/changes/10220-back2school/00-entryLog.sql similarity index 99% rename from db/changes/10220-back2school/00-entryLog copy.sql rename to db/changes/10220-back2school/00-entryLog.sql index 0e2551501..9af6ad5f2 100644 --- a/db/changes/10220-back2school/00-entryLog copy.sql +++ b/db/changes/10220-back2school/00-entryLog.sql @@ -4,3 +4,4 @@ ADD COLUMN `oldInstance` text CHARACTER SET utf8 COLLATE utf8_unicode_ci, ADD COLUMN `newInstance` text CHARACTER SET utf8 COLLATE utf8_unicode_ci, ADD COLUMN `changedModelId` int(11) DEFAULT NULL, ADD COLUMN `changedModelValue` varchar(45) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL; + From 71e29e747a5df9ced4d58af228bd2b236448e8ab Mon Sep 17 00:00:00 2001 From: joan Date: Mon, 5 Oct 2020 14:45:39 +0200 Subject: [PATCH 14/18] Requested changes --- back/methods/campaign/spec/latest.spec.js | 24 ++++++++++--- back/methods/campaign/upcoming.js | 7 ++-- front/core/components/autocomplete/index.js | 3 -- .../front/consumption-search-panel/index.html | 2 +- .../consumption-search-panel/index.spec.js | 2 +- .../worker/specs/createAbsence.spec.js | 11 +++--- .../worker/specs/deleteAbsence.spec.js | 23 ++++++------ .../worker/specs/updateAbsence.spec.js | 35 +++++++++++++------ 8 files changed, 66 insertions(+), 41 deletions(-) diff --git a/back/methods/campaign/spec/latest.spec.js b/back/methods/campaign/spec/latest.spec.js index c76231ab2..b76e4fd0a 100644 --- a/back/methods/campaign/spec/latest.spec.js +++ b/back/methods/campaign/spec/latest.spec.js @@ -2,17 +2,33 @@ const app = require('vn-loopback/server/server'); describe('campaign latest()', () => { it('should return the campaigns from the last year', async() => { - let response = await app.models.Campaign.latest(); + let result = await app.models.Campaign.latest(); const lastYearDate = new Date(); lastYearDate.setFullYear(lastYearDate.getFullYear() - 1); const lastYear = lastYearDate.getFullYear(); - const randomIndex = Math.floor(Math.random() * 3); - const campaignDated = response[randomIndex].dated; + const randomIndex = Math.floor(Math.random() * result.length); + const campaignDated = result[randomIndex].dated; const campaignYear = campaignDated.getFullYear(); - expect(response.length).toEqual(3); + expect(result.length).toEqual(3); expect(campaignYear).toEqual(lastYear); }); + + it('should return the campaigns from the current year', async() => { + const currentDate = new Date(); + const currentYear = currentDate.getFullYear(); + + const result = await app.models.Campaign.latest({ + where: {dated: {like: `%${currentYear}%`}} + }); + + const randomIndex = Math.floor(Math.random() * result.length); + const campaignDated = result[randomIndex].dated; + const campaignYear = campaignDated.getFullYear(); + + expect(result.length).toEqual(3); + expect(campaignYear).toEqual(currentYear); + }); }); diff --git a/back/methods/campaign/upcoming.js b/back/methods/campaign/upcoming.js index cc9f7f910..cabb66705 100644 --- a/back/methods/campaign/upcoming.js +++ b/back/methods/campaign/upcoming.js @@ -15,16 +15,15 @@ module.exports = Self => { Self.upcoming = async() => { const minDate = new Date(); - minDate.setMonth(0); - minDate.setDate(1); + minDate.setFullYear(minDate.getFullYear() - 1); return Self.findOne({ where: { dated: { - lt: minDate + gte: minDate } }, - order: 'dated DESC' + order: 'dated ASC' }); }; }; diff --git a/front/core/components/autocomplete/index.js b/front/core/components/autocomplete/index.js index 742ad6f2a..18c277f06 100755 --- a/front/core/components/autocomplete/index.js +++ b/front/core/components/autocomplete/index.js @@ -208,9 +208,6 @@ export default class Autocomplete extends Field { } this.input.value = display; - - /* if (this.translateFields.indexOf(this.showField) > -1) - this.input.value = this.$t(display); */ } } diff --git a/modules/client/front/consumption-search-panel/index.html b/modules/client/front/consumption-search-panel/index.html index 0edb0b34a..f8d633c71 100644 --- a/modules/client/front/consumption-search-panel/index.html +++ b/modules/client/front/consumption-search-panel/index.html @@ -59,7 +59,7 @@ ng-model="filter.campaign" order="dated DESC" selection="$ctrl.campaignSelection" - search-function="{or: [{dated: {like: '%'+ $search +'%'}}]}"> + search-function="{dated: {like: '%'+ $search +'%'}}"> {{code}} {{dated | date: 'yyyy'}} diff --git a/modules/client/front/consumption-search-panel/index.spec.js b/modules/client/front/consumption-search-panel/index.spec.js index dfab07086..7209fe3c3 100644 --- a/modules/client/front/consumption-search-panel/index.spec.js +++ b/modules/client/front/consumption-search-panel/index.spec.js @@ -17,7 +17,7 @@ describe('Client', () => { })); describe('getUpcomingCampaing()', () => { - it(`should make an HTTP GET query`, () => { + it(`should make an HTTP query and then set the campaign property`, () => { $httpBackend.expect('GET', 'Campaigns/upcoming').respond(200, {id: 2, code: 'allSaints'}); controller.getUpcomingCampaing(); $httpBackend.flush(); diff --git a/modules/worker/back/methods/worker/specs/createAbsence.spec.js b/modules/worker/back/methods/worker/specs/createAbsence.spec.js index 324dab99d..ace412890 100644 --- a/modules/worker/back/methods/worker/specs/createAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/createAbsence.spec.js @@ -3,12 +3,6 @@ const LoopBackContext = require('loopback-context'); describe('Worker createAbsence()', () => { const workerId = 18; - let createdAbsence; - - afterAll(async() => { - const absence = await app.models.Calendar.findById(createdAbsence.id); - await absence.destroy(); - }); it('should return an error for a user without enough privileges', async() => { const ctx = {req: {accessToken: {userId: 18}}}; @@ -40,12 +34,15 @@ describe('Worker createAbsence()', () => { const absenceTypeId = 1; const dated = new Date(); - createdAbsence = await app.models.Worker.createAbsence(ctx, workerId, absenceTypeId, dated); + const createdAbsence = await app.models.Worker.createAbsence(ctx, workerId, absenceTypeId, dated); const expectedBusinessId = 18; const expectedAbsenceTypeId = 1; expect(createdAbsence.businessFk).toEqual(expectedBusinessId); expect(createdAbsence.dayOffTypeFk).toEqual(expectedAbsenceTypeId); + + // Restores + await app.models.Calendar.destroyById(createdAbsence.id); }); }); diff --git a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js index 2f72a8435..15bd854ed 100644 --- a/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/deleteAbsence.spec.js @@ -2,29 +2,35 @@ const app = require('vn-loopback/server/server'); const LoopBackContext = require('loopback-context'); describe('Worker deleteAbsence()', () => { + const businessId = 18; const workerId = 18; - let createdAbsence; const activeCtx = { - accessToken: {userId: 19}, + accessToken: {userId: 106}, headers: {origin: 'http://localhost'} }; const ctx = {req: activeCtx}; ctx.req.__ = value => { return value; }; + let createdAbsence; - it('should return an error for a user without enough privileges', async() => { + beforeEach(async() => { spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ active: activeCtx }); - - activeCtx.accessToken.userId = 106; - const businessId = 18; createdAbsence = await app.models.Calendar.create({ businessFk: businessId, dayOffTypeFk: 1, dated: new Date() }); + }); + + afterEach(async() => { + await app.models.Calendar.destroyById(createdAbsence.id); + }); + + it('should return an error for a user without enough privileges', async() => { + activeCtx.accessToken.userId = 106; let error; await app.models.Worker.deleteAbsence(ctx, 18, createdAbsence.id).catch(e => { @@ -37,12 +43,7 @@ describe('Worker deleteAbsence()', () => { }); it('should create a new absence', async() => { - spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ - active: activeCtx - }); - activeCtx.accessToken.userId = 19; - const businessId = 18; expect(createdAbsence.businessFk).toEqual(businessId); diff --git a/modules/worker/back/methods/worker/specs/updateAbsence.spec.js b/modules/worker/back/methods/worker/specs/updateAbsence.spec.js index 1b34cf2e0..2ff8e64e1 100644 --- a/modules/worker/back/methods/worker/specs/updateAbsence.spec.js +++ b/modules/worker/back/methods/worker/specs/updateAbsence.spec.js @@ -1,22 +1,37 @@ const app = require('vn-loopback/server/server'); +const LoopBackContext = require('loopback-context'); describe('Worker updateAbsence()', () => { const workerId = 106; + const businessId = 106; + const activeCtx = { + accessToken: {userId: 106}, + headers: {origin: 'http://localhost'} + }; + const ctx = {req: activeCtx}; + ctx.req.__ = value => { + return value; + }; let createdAbsence; - afterAll(async() => { - const absence = await app.models.Calendar.findById(createdAbsence.id); - await absence.destroy(); - }); - - it('should return an error for a user without enough privileges', async() => { - const ctx = {req: {accessToken: {userId: 106}}}; - const expectedAbsenceTypeId = 2; + beforeEach(async() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); createdAbsence = await app.models.Calendar.create({ - businessFk: 106, + businessFk: businessId, dayOffTypeFk: 1, dated: new Date() }); + }); + + afterEach(async() => { + await app.models.Calendar.destroyById(createdAbsence.id); + }); + + it('should return an error for a user without enough privileges', async() => { + activeCtx.accessToken.userId = 106; + const expectedAbsenceTypeId = 2; let error; await app.models.Worker.updateAbsence(ctx, workerId, createdAbsence.id, expectedAbsenceTypeId).catch(e => { @@ -29,7 +44,7 @@ describe('Worker updateAbsence()', () => { }); it('should create a new absence', async() => { - const ctx = {req: {accessToken: {userId: 37}}}; + activeCtx.accessToken.userId = 37; const expectedAbsenceTypeId = 2; const updatedAbsence = await app.models.Worker.updateAbsence(ctx, workerId, createdAbsence.id, expectedAbsenceTypeId); From 91fa3e2aec912783964f0edcc96304e6cef6c015 Mon Sep 17 00:00:00 2001 From: joan Date: Mon, 5 Oct 2020 14:47:42 +0200 Subject: [PATCH 15/18] Updated description --- back/methods/campaign/upcoming.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/methods/campaign/upcoming.js b/back/methods/campaign/upcoming.js index cabb66705..2f1a5a377 100644 --- a/back/methods/campaign/upcoming.js +++ b/back/methods/campaign/upcoming.js @@ -1,6 +1,6 @@ module.exports = Self => { Self.remoteMethod('upcoming', { - description: 'Returns the lastest campaigns', + description: 'Returns the upcoming campaign', accessType: 'READ', accepts: [], returns: { From 0b8d8a4f65f264a4a761899d8cb6474b6bbe2cd0 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 6 Oct 2020 08:17:12 +0200 Subject: [PATCH 16/18] Added focus directive to searchbar --- modules/claim/front/main/index.html | 1 + modules/client/front/main/index.html | 1 + modules/client/front/routes.json | 4 ++-- modules/entry/front/latest-buys/index.html | 1 + modules/entry/front/main/index.html | 1 + modules/invoiceOut/front/main/index.html | 1 + modules/item/front/main/index.html | 1 + modules/order/front/main/index.html | 1 + modules/route/front/main/index.html | 1 + modules/ticket/front/main/index.html | 1 + modules/ticket/front/weekly/index.html | 1 + modules/travel/front/main/index.html | 1 + modules/worker/front/main/index.html | 1 + modules/zone/front/main/index.html | 1 + 14 files changed, 15 insertions(+), 2 deletions(-) diff --git a/modules/claim/front/main/index.html b/modules/claim/front/main/index.html index 8a9447125..f38cc573f 100644 --- a/modules/claim/front/main/index.html +++ b/modules/claim/front/main/index.html @@ -7,6 +7,7 @@ diff --git a/modules/client/front/main/index.html b/modules/client/front/main/index.html index cab796c1f..e8bc4b988 100644 --- a/modules/client/front/main/index.html +++ b/modules/client/front/main/index.html @@ -7,6 +7,7 @@ diff --git a/modules/invoiceOut/front/main/index.html b/modules/invoiceOut/front/main/index.html index df65fd217..7f3e67f35 100644 --- a/modules/invoiceOut/front/main/index.html +++ b/modules/invoiceOut/front/main/index.html @@ -6,6 +6,7 @@ diff --git a/modules/item/front/main/index.html b/modules/item/front/main/index.html index 55ef00b75..a57d4fb2d 100644 --- a/modules/item/front/main/index.html +++ b/modules/item/front/main/index.html @@ -7,6 +7,7 @@ diff --git a/modules/zone/front/main/index.html b/modules/zone/front/main/index.html index d5a2b2b38..8dd6cdf78 100644 --- a/modules/zone/front/main/index.html +++ b/modules/zone/front/main/index.html @@ -6,6 +6,7 @@ Date: Tue, 6 Oct 2020 08:52:11 +0200 Subject: [PATCH 17/18] 2486 - Changed date filter --- modules/item/front/last-entries/index.html | 24 +++++++++++----------- modules/item/front/last-entries/index.js | 11 +++++++++- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/modules/item/front/last-entries/index.html b/modules/item/front/last-entries/index.html index f306fb4f0..1f7c3c364 100644 --- a/modules/item/front/last-entries/index.html +++ b/modules/item/front/last-entries/index.html @@ -7,25 +7,25 @@ order="landed DESC, buyFk DESC" limit="20"> + + + + + - - - - - Ig Warehouse - Landed + Landed Entry P.P.U P.P.P @@ -48,8 +48,8 @@ disabled="true"> - {{::entry.warehouse| dashIfEmpty}} - {{::entry.landed | date:'dd/MM/yyyy HH:mm'}} + {{::entry.warehouse| dashIfEmpty}} + {{::entry.landed | date:'dd/MM/yyyy HH:mm'}} {{::entry.entryFk | dashIfEmpty}} {{::entry.price2 | dashIfEmpty}} {{::entry.price3 | dashIfEmpty}} @@ -69,7 +69,7 @@ {{::entry.buyingValue | dashIfEmpty}} {{::entry.weight | dashIfEmpty}} {{::entry.packageFk | dashIfEmpty}} - {{::entry.supplier | dashIfEmpty}} + {{::entry.supplier | dashIfEmpty}} diff --git a/modules/item/front/last-entries/index.js b/modules/item/front/last-entries/index.js index 11a2bf20e..4a72c0caa 100644 --- a/modules/item/front/last-entries/index.js +++ b/modules/item/front/last-entries/index.js @@ -30,7 +30,16 @@ class Controller extends Section { if (!value) return; - this.filter.where.date = value; + const from = new Date(value); + from.setHours(0, 0, 0, 0); + + const to = new Date(); + to.setDate(to.getDate() + 10); + to.setHours(23, 59, 59, 59); + + this.filter.where.shipped = { + between: [from, to] + }; this.$.model.refresh(); } From 2856fa63fcff4f9cbc9f68af030e1d49712e1976 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 6 Oct 2020 09:50:40 +0200 Subject: [PATCH 18/18] Added ACL for module account --- modules/account/front/routes.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/account/front/routes.json b/modules/account/front/routes.json index 7316fff94..36caf8644 100644 --- a/modules/account/front/routes.json +++ b/modules/account/front/routes.json @@ -39,7 +39,8 @@ "url": "/index?q", "state": "account.index", "component": "vn-user-index", - "description": "Users" + "description": "Users", + "acl": ["hr"] }, { "url": "/create", "state": "account.create",