From 84a5f3986b5aaa838a6882cfbdd24dff1e0d8561 Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 2 Nov 2022 13:24:35 +0100 Subject: [PATCH 01/18] feat(worker): createWorker refs #4658 --- modules/worker/back/methods/worker/new.js | 197 ++++++++++++++++++++++ modules/worker/back/models/worker.js | 1 + 2 files changed, 198 insertions(+) create mode 100644 modules/worker/back/methods/worker/new.js diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js new file mode 100644 index 000000000..481011563 --- /dev/null +++ b/modules/worker/back/methods/worker/new.js @@ -0,0 +1,197 @@ +const md5 = require('md5'); +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('new', { + description: 'Creates a new ticket and returns the id', + accessType: 'WRITE', + accepts: [ + { + arg: 'fi', + type: 'number', + description: `The fi of worker`, + required: true + }, + { + arg: 'name', + type: 'string', + description: `REPLACE!`, + required: true + }, + { + arg: 'firstName', + type: 'string', + description: `REPLACE!`, + required: true + }, + { + arg: 'lastNames', + type: 'string', + description: `REPLACE!`, + required: true + }, + { + arg: 'password', + type: 'string', + description: `REPLACE!`, + required: true + }, + { + arg: 'email', + type: 'string', + description: `REPLACE!`, + required: true + }, + { + arg: 'role', + type: 'number', + description: `REPLACE!` + }, + { + arg: 'street', + type: 'string', + description: `REPLACE!` + }, + { + arg: 'string', + type: 'number', + description: `REPLACE!` + }, + { + arg: 'provinceFk', + type: 'number', + description: `REPLACE!` + }, + { + arg: 'postalCode', + type: 'number', + description: `REPLACE!` + }, + { + arg: 'phone', + type: 'number', + description: `REPLACE!` + }, + { + arg: 'workerCode', + type: 'string', + description: `REPLACE!` + }, + { + arg: 'bossFk', + type: 'number', + description: `REPLACE!` + }, + { + arg: 'birth', + type: 'date', + description: `REPLACE!` + } + ], + returns: { + type: 'number', + root: true + }, + http: { + path: `/new`, + verb: 'POST' + } + }); + + Self.new = async(ctx, options) => { + const models = Self.app.models; + const myOptions = {}; + const args = ctx.args; + + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + let client; + try { + client = await models.Client.findOne({ + where: {fi: fi}, + }, myOptions); + + if (!client) { + const nickname = args.firstName.concat(' ', args.lastNames); + const user = await models.Account.create({ + name: args.name, + nickname, + password: md5(args.password), + email: args.email, + role: args.role + }, myOptions); + + await models.UserAccount.create({ + id: user.id + }, myOptions); + + await models.Worker.rawSql('CALL vn.clientCreate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + [ + args.firstName, + args.lastNames, + args.fi, + args.address, + args.postalCode, + args.town, + args.province, + args.company, + args.phone, + args.email, + user.id + ] + , myOptions); + + const address = await models.Address.create({ + clientFk: user.id, + address: args.street, + town: args.town, + provinceFk: args.provinceFk, + postalCode: args.postalCode, + mobile: args.phone, + nickname: 'TR ' + nickname, + isDefaultAddress: true + }, myOptions); + + client = await models.Sale.findById(user.id, null, myOptions); + await client.updateAttribute('defaultAddressFk ', address.id); + } + + await models.Worker.rawSql('CALL vn.workerCreate(?, ?, ?, ?, ?, ?, ?)', + [ + args.firstName, + args.lastNames, + args.workerCode, + args.bossFk, + user.id, + args.fi, + args.birth + ] + , myOptions); + + if (tx) await tx.commit(); + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + + // TODO: create this email, use client-welcome as template. And view CALL mail_insert in redmine for the body + // TODO: or use same funcionality back/methods/account/recover-password.js + const email = new Email('worker-welcome', { + recipient: args.email, + lang: ctx.req.getLocale() + }); + + await email.send(); + + // return id, and in front use for redirection + return client.id; + }; +}; diff --git a/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js index ec6c4af28..e66259cd0 100644 --- a/modules/worker/back/models/worker.js +++ b/modules/worker/back/models/worker.js @@ -13,4 +13,5 @@ module.exports = Self => { require('../methods/worker/contracts')(Self); require('../methods/worker/holidays')(Self); require('../methods/worker/activeContract')(Self); + require('../methods/worker/new')(Self); }; From db3a6df23d3bb04fb398d6d02748323fe1454d14 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 14 Nov 2022 15:19:16 +0100 Subject: [PATCH 02/18] feat(worker): new worker --- .../10503-november/00-aclProfileType.sql | 18 ++ db/dump/fixtures.sql | 8 + modules/worker/back/methods/worker/new.js | 102 ++++++--- modules/worker/back/model-config.json | 18 +- .../worker/back/models/new-worker-config.json | 39 ++++ modules/worker/back/models/profile-type.json | 19 ++ modules/worker/back/models/worker.json | 5 +- modules/worker/front/create/index.html | 208 ++++++++++++++++++ modules/worker/front/create/index.js | 98 +++++++++ modules/worker/front/create/index.spec.js | 122 ++++++++++ modules/worker/front/create/locale/es.yml | 12 + modules/worker/front/index.js | 1 + modules/worker/front/index/index.html | 6 + modules/worker/front/routes.json | 11 +- .../email/worker-welcome/assets/css/import.js | 11 + .../email/worker-welcome/client-welcome.html | 10 + .../email/worker-welcome/client-welcome.js | 23 ++ .../email/worker-welcome/locale/es.yml | 7 + .../email/worker-welcome/sql/client.sql | 11 + 19 files changed, 684 insertions(+), 45 deletions(-) create mode 100644 db/changes/10503-november/00-aclProfileType.sql create mode 100644 modules/worker/back/models/new-worker-config.json create mode 100644 modules/worker/back/models/profile-type.json create mode 100644 modules/worker/front/create/index.html create mode 100644 modules/worker/front/create/index.js create mode 100644 modules/worker/front/create/index.spec.js create mode 100644 modules/worker/front/create/locale/es.yml create mode 100644 print/templates/email/worker-welcome/assets/css/import.js create mode 100644 print/templates/email/worker-welcome/client-welcome.html create mode 100755 print/templates/email/worker-welcome/client-welcome.js create mode 100644 print/templates/email/worker-welcome/locale/es.yml create mode 100644 print/templates/email/worker-welcome/sql/client.sql diff --git a/db/changes/10503-november/00-aclProfileType.sql b/db/changes/10503-november/00-aclProfileType.sql new file mode 100644 index 000000000..638b3d580 --- /dev/null +++ b/db/changes/10503-november/00-aclProfileType.sql @@ -0,0 +1,18 @@ + +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('ProfileType', '*', '*', 'ALLOW', 'ROLE', 'employee'); + +CREATE TABLE `vn`.`newWorkerConfig` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `street` VARCHAR(25) NULL, + `provinceFk` smallint(6) unsigned NULL, + `companyFk` smallint(5) unsigned NULL, + `profileTypeFk` INT(11) NULL, + `roleFk` int(10) unsigned NULL, + PRIMARY KEY (`id`), + CONSTRAINT `newWorkerConfig_province_fk` FOREIGN KEY (`provinceFk`) REFERENCES `vn`.`province` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `newWorkerConfig_company_fk` FOREIGN KEY (`companyFk`) REFERENCES `vn`.`company` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `newWorkerConfig_profileType_fk` FOREIGN KEY (`profileTypeFk`) REFERENCES `vn`.`profileType` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `newWorkerConfig_role_fk` FOREIGN KEY (`roleFk`) REFERENCES `account`.`role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +); diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 6624e99f4..a6fb9cbbb 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2719,3 +2719,11 @@ UPDATE `account`.`user` INSERT INTO `vn`.`osTicketConfig` (`id`, `host`, `user`, `password`, `oldStatus`, `newStatusId`, `day`, `comment`, `hostDb`, `userDb`, `passwordDb`, `portDb`, `responseType`, `fromEmailId`, `replyTo`) VALUES (0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', 'open', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all'); + +INSERT INTO `vn`.`profileType` (`id`, `name`) + VALUES + (1, 'working'); + +INSERT INTO `vn`.`newWorkerConfig` (`id`, `street`, `provinceFk`, `companyFk`, `profileTypeFk`, `roleFk`) + VALUES + (1, 'S/ ', 1, 442, 1, 1); diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js index 481011563..bdab1335a 100644 --- a/modules/worker/back/methods/worker/new.js +++ b/modules/worker/back/methods/worker/new.js @@ -8,7 +8,7 @@ module.exports = Self => { accepts: [ { arg: 'fi', - type: 'number', + type: 'string', description: `The fi of worker`, required: true }, @@ -30,12 +30,6 @@ module.exports = Self => { description: `REPLACE!`, required: true }, - { - arg: 'password', - type: 'string', - description: `REPLACE!`, - required: true - }, { arg: 'email', type: 'string', @@ -43,49 +37,76 @@ module.exports = Self => { required: true }, { - arg: 'role', + arg: 'roleFk', type: 'number', - description: `REPLACE!` + description: `REPLACE!`, + required: true }, { arg: 'street', type: 'string', - description: `REPLACE!` + description: `REPLACE!`, + required: true }, { - arg: 'string', - type: 'number', - description: `REPLACE!` + arg: 'city', + type: 'string', + description: `REPLACE!`, + required: true }, { arg: 'provinceFk', type: 'number', - description: `REPLACE!` + description: `REPLACE!`, + required: true }, { - arg: 'postalCode', + arg: 'iban', + type: 'string', + description: `REPLACE!`, + required: true + }, + { + arg: 'bankEntityFk', type: 'number', - description: `REPLACE!` + description: `REPLACE!`, + required: true + }, + { + arg: 'companyFk', + type: 'number', + description: `REPLACE!`, + required: true + }, + { + arg: 'postcode', + type: 'string', + description: `REPLACE!`, + required: true }, { arg: 'phone', - type: 'number', - description: `REPLACE!` + type: 'string', + description: `REPLACE!`, + required: true }, { - arg: 'workerCode', + arg: 'code', type: 'string', - description: `REPLACE!` + description: `REPLACE!`, + required: true }, { arg: 'bossFk', type: 'number', - description: `REPLACE!` + description: `REPLACE!`, + required: true }, { arg: 'birth', type: 'date', - description: `REPLACE!` + description: `REPLACE!`, + required: true } ], returns: { @@ -104,7 +125,7 @@ module.exports = Self => { const args = ctx.args; let tx; - + console.log(args); if (typeof options == 'object') Object.assign(myOptions, options); @@ -116,15 +137,16 @@ module.exports = Self => { let client; try { client = await models.Client.findOne({ - where: {fi: fi}, + where: {fi: args.fi}, }, myOptions); if (!client) { const nickname = args.firstName.concat(' ', args.lastNames); + const randomPassword = await models.Worker.rawSql('SELECT account.passwordGenerate();'); const user = await models.Account.create({ name: args.name, nickname, - password: md5(args.password), + password: md5(randomPassword), email: args.email, role: args.role }, myOptions); @@ -138,11 +160,11 @@ module.exports = Self => { args.firstName, args.lastNames, args.fi, - args.address, + args.street, args.postalCode, - args.town, - args.province, - args.company, + args.city, + args.provinceFk, + args.companyFk, args.phone, args.email, user.id @@ -151,8 +173,8 @@ module.exports = Self => { const address = await models.Address.create({ clientFk: user.id, - address: args.street, - town: args.town, + street: args.street, + city: args.city, provinceFk: args.provinceFk, postalCode: args.postalCode, mobile: args.phone, @@ -160,17 +182,22 @@ module.exports = Self => { isDefaultAddress: true }, myOptions); - client = await models.Sale.findById(user.id, null, myOptions); - await client.updateAttribute('defaultAddressFk ', address.id); - } + client = await models.Client.findById(user.id, null, myOptions); + console.log(address.id); + await client.updateAttributes({ + iban: args.iban, + bankEntityFk: args.bankEntityFk, + defaultAddressFk: address.id + }, myOptions); + } await models.Worker.rawSql('CALL vn.workerCreate(?, ?, ?, ?, ?, ?, ?)', [ args.firstName, args.lastNames, - args.workerCode, + args.code, args.bossFk, - user.id, + client.id, args.fi, args.birth ] @@ -184,6 +211,9 @@ module.exports = Self => { // TODO: create this email, use client-welcome as template. And view CALL mail_insert in redmine for the body // TODO: or use same funcionality back/methods/account/recover-password.js + + // TODO: call worerWelcomeEmail, and this is who create the url for change password + const email = new Email('worker-welcome', { recipient: args.email, lang: ctx.req.getLocale() diff --git a/modules/worker/back/model-config.json b/modules/worker/back/model-config.json index 3f3416504..de8aadd41 100644 --- a/modules/worker/back/model-config.json +++ b/modules/worker/back/model-config.json @@ -1,7 +1,7 @@ { "AbsenceType": { "dataSource": "vn" - }, + }, "Calendar": { "dataSource": "vn" }, @@ -16,13 +16,22 @@ }, "Department": { "dataSource": "vn" - }, + }, + "Device": { + "dataSource": "vn" + }, "EducationLevel": { "dataSource": "vn" }, "Journey": { "dataSource": "vn" }, + "NewWorkerConfig":{ + "dataSource": "vn" + }, + "ProfileType":{ + "dataSource": "vn" + }, "Time": { "dataSource": "vn" }, @@ -55,11 +64,8 @@ }, "WorkerDepartment": { "dataSource": "vn" - }, - "WorkerTimeControl": { - "dataSource": "vn" }, - "Device": { + "WorkerTimeControl": { "dataSource": "vn" }, "WorkerLog": { diff --git a/modules/worker/back/models/new-worker-config.json b/modules/worker/back/models/new-worker-config.json new file mode 100644 index 000000000..2102d236c --- /dev/null +++ b/modules/worker/back/models/new-worker-config.json @@ -0,0 +1,39 @@ +{ + "name": "NewWorkerConfig", + "base": "VnModel", + "options": { + "mysql": { + "table": "newWorkerConfig" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "street": { + "type": "string" + }, + "provinceFk": { + "type": "number" + }, + "companyFk": { + "type": "number" + }, + "profileTypeFk": { + "type": "number" + }, + "roleFk": { + "type": "number" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} diff --git a/modules/worker/back/models/profile-type.json b/modules/worker/back/models/profile-type.json new file mode 100644 index 000000000..d1d750de8 --- /dev/null +++ b/modules/worker/back/models/profile-type.json @@ -0,0 +1,19 @@ +{ + "name": "ProfileType", + "base": "VnModel", + "options": { + "mysql": { + "table": "profileType" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "name": { + "type": "string" + } + } +} diff --git a/modules/worker/back/models/worker.json b/modules/worker/back/models/worker.json index 3d41707ce..e3a941dd3 100644 --- a/modules/worker/back/models/worker.json +++ b/modules/worker/back/models/worker.json @@ -52,6 +52,9 @@ }, "mobileExtension": { "type" : "number" + }, + "code": { + "type" : "string" } }, "relations": { @@ -91,4 +94,4 @@ "foreignKey": "sectorFk" } } -} \ No newline at end of file +} diff --git a/modules/worker/front/create/index.html b/modules/worker/front/create/index.html new file mode 100644 index 000000000..58b4da060 --- /dev/null +++ b/modules/worker/front/create/index.html @@ -0,0 +1,208 @@ + + +
+ + + + + + + + + + + + + + + + + + + + {{name}} ({{country.country}}) + + + + {{name}}, {{province.name}} + ({{province.country.country}}) + + + + + + + {{code}} - {{town.name}} ({{town.province.name}}, + {{town.province.country.country}}) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{bic}} {{name}} + + + + + + + + + + + + + +
+ + + diff --git a/modules/worker/front/create/index.js b/modules/worker/front/create/index.js new file mode 100644 index 000000000..a068b2006 --- /dev/null +++ b/modules/worker/front/create/index.js @@ -0,0 +1,98 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + this.$http.get('NewWorkerConfigs/findOne').then(res => { + return this.worker = Object.assign({}, res.data); + }); + } + + onSubmit() { + return this.$.watcher.submit().then(json => { + this.$state.go('client.card.basicData', {id: json.data.id}); + this.$http.get(`Clients/${this.client.id}/checkDuplicatedData`); + }); + } + + autofillBic() { + if (!this.worker || !this.worker.iban) return; + + let bankEntityId = parseInt(this.worker.iban.substr(4, 4)); + let filter = {where: {id: bankEntityId}}; + + if (this.ibanCountry != 'ES') return; + + this.$http.get(`BankEntities`, {filter}).then(response => { + const hasData = response.data && response.data[0]; + + if (hasData) + this.worker.bankEntityFk = response.data[0].id; + else if (!hasData) + this.worker.bankEntityFk = null; + }); + } + + get province() { + return this._province; + } + + // Province auto complete + set province(selection) { + this._province = selection; + } + + get town() { + return this._town; + } + + // Town auto complete + set town(selection) { + this._town = selection; + + if (!selection) return; + + const province = selection.province; + const postcodes = selection.postcodes; + + if (!this.client.provinceFk) + this.client.provinceFk = province.id; + + if (postcodes.length === 1) + this.client.postcode = postcodes[0].code; + } + + get postcode() { + return this._postcode; + } + + // Postcode auto complete + set postcode(selection) { + this._postcode = selection; + + if (!selection) return; + + const town = selection.town; + const province = town.province; + + if (!this.client.city) + this.client.city = town.name; + + if (!this.client.provinceFk) + this.client.provinceFk = province.id; + } + + onResponse(response) { + this.client.postcode = response.code; + this.client.city = response.city; + this.client.provinceFk = response.provinceFk; + } +} + +Controller.$inject = ['$element', '$scope']; + +ngModule.vnComponent('vnWorkerCreate', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/worker/front/create/index.spec.js b/modules/worker/front/create/index.spec.js new file mode 100644 index 000000000..24fc80d21 --- /dev/null +++ b/modules/worker/front/create/index.spec.js @@ -0,0 +1,122 @@ +import './index'; + +describe('Client', () => { + describe('Component vnClientCreate', () => { + let $scope; + let $state; + let controller; + + beforeEach(ngModule('client')); + + beforeEach(inject(($componentController, $rootScope, _$state_) => { + $scope = $rootScope.$new(); + $state = _$state_; + $scope.watcher = { + submit: () => { + return { + then: callback => { + callback({data: {id: '1234'}}); + } + }; + } + }; + const $element = angular.element(''); + controller = $componentController('vnClientCreate', {$element, $scope}); + })); + + it('should define and set scope, state and client properties', () => { + expect(controller.$).toBe($scope); + expect(controller.$state).toBe($state); + expect(controller.client.active).toBe(true); + }); + + describe('onSubmit()', () => { + it(`should call submit() on the watcher then expect a callback`, () => { + jest.spyOn($state, 'go'); + controller.onSubmit(); + + expect(controller.$state.go).toHaveBeenCalledWith('client.card.basicData', {id: '1234'}); + }); + }); + + describe('province() setter', () => { + it(`should set countryFk property`, () => { + controller.client.countryFk = null; + controller.province = { + id: 1, + name: 'New york', + country: { + id: 2, + name: 'USA' + } + }; + + expect(controller.client.countryFk).toEqual(2); + }); + }); + + describe('town() setter', () => { + it(`should set provinceFk property`, () => { + controller.town = { + provinceFk: 1, + code: 46001, + province: { + id: 1, + name: 'New york', + country: { + id: 2, + name: 'USA' + } + }, + postcodes: [] + }; + + expect(controller.client.provinceFk).toEqual(1); + }); + + it(`should set provinceFk property and fill the postalCode if there's just one`, () => { + controller.town = { + provinceFk: 1, + code: 46001, + province: { + id: 1, + name: 'New york', + country: { + id: 2, + name: 'USA' + } + }, + postcodes: [{code: '46001'}] + }; + + expect(controller.client.provinceFk).toEqual(1); + expect(controller.client.postcode).toEqual('46001'); + }); + }); + + describe('postcode() setter', () => { + it(`should set the town, provinceFk and contryFk properties`, () => { + controller.postcode = { + townFk: 1, + code: 46001, + town: { + id: 1, + name: 'New York', + province: { + id: 1, + name: 'New york', + country: { + id: 2, + name: 'USA' + } + } + } + }; + + expect(controller.client.city).toEqual('New York'); + expect(controller.client.provinceFk).toEqual(1); + expect(controller.client.countryFk).toEqual(2); + }); + }); + }); +}); diff --git a/modules/worker/front/create/locale/es.yml b/modules/worker/front/create/locale/es.yml new file mode 100644 index 000000000..afe3feaa6 --- /dev/null +++ b/modules/worker/front/create/locale/es.yml @@ -0,0 +1,12 @@ +Name: Nombre +Tax number: NIF/CIF +Business name: Razón social +Web user: Usuario Web +Email: E-mail +Create and edit: Crear y editar +You can save multiple emails: >- + Puede guardar varios correos electrónicos encadenándolos mediante comas + sin espacios, ejemplo: user@dominio.com, user2@dominio.com siendo el primer + correo electrónico el principal +The type of business must be filled in basic data: El tipo de negocio debe estar rellenado en datos básicos +Access permission: Permiso de acceso diff --git a/modules/worker/front/index.js b/modules/worker/front/index.js index f703e7c21..97126407c 100644 --- a/modules/worker/front/index.js +++ b/modules/worker/front/index.js @@ -4,6 +4,7 @@ import './main'; import './index/'; import './summary'; import './card'; +import './create'; import './descriptor'; import './descriptor-popover'; import './search-panel'; diff --git a/modules/worker/front/index/index.html b/modules/worker/front/index/index.html index 98df416b4..b48a84854 100644 --- a/modules/worker/front/index/index.html +++ b/modules/worker/front/index/index.html @@ -42,6 +42,12 @@ + + + diff --git a/modules/worker/front/routes.json b/modules/worker/front/routes.json index ca33eaa76..dad55512b 100644 --- a/modules/worker/front/routes.json +++ b/modules/worker/front/routes.json @@ -16,7 +16,7 @@ {"state": "worker.card.timeControl", "icon": "access_time"}, {"state": "worker.card.dms.index", "icon": "cloud_upload"}, { - "icon": "icon-wiki", + "icon": "icon-wiki", "external":true, "url": "http://wiki.verdnatura.es", "description": "Wikipedia" @@ -134,6 +134,13 @@ "worker": "$ctrl.worker" }, "acl": ["hr"] + }, + { + "url": "/create", + "state": "worker.create", + "component": "vn-worker-create", + "description": "New worker", + "acl": ["hr"] } ] -} \ No newline at end of file +} diff --git a/print/templates/email/worker-welcome/assets/css/import.js b/print/templates/email/worker-welcome/assets/css/import.js new file mode 100644 index 000000000..4b4bb7086 --- /dev/null +++ b/print/templates/email/worker-welcome/assets/css/import.js @@ -0,0 +1,11 @@ +const Stylesheet = require(`vn-print/core/stylesheet`); + +const path = require('path'); +const vnPrintPath = path.resolve('print'); + +module.exports = new Stylesheet([ + `${vnPrintPath}/common/css/spacing.css`, + `${vnPrintPath}/common/css/misc.css`, + `${vnPrintPath}/common/css/layout.css`, + `${vnPrintPath}/common/css/email.css`]) + .mergeStyles(); diff --git a/print/templates/email/worker-welcome/client-welcome.html b/print/templates/email/worker-welcome/client-welcome.html new file mode 100644 index 000000000..6aaee6120 --- /dev/null +++ b/print/templates/email/worker-welcome/client-welcome.html @@ -0,0 +1,10 @@ + +
+
+

{{ $t('title', [id]) }}

+

{{ $t('description.dearWorker') }},

+

+

{{ $t('workerData', this.user.name, this.url) }}

+
+
+
diff --git a/print/templates/email/worker-welcome/client-welcome.js b/print/templates/email/worker-welcome/client-welcome.js new file mode 100755 index 000000000..9fbcf86a6 --- /dev/null +++ b/print/templates/email/worker-welcome/client-welcome.js @@ -0,0 +1,23 @@ +const Component = require(`vn-print/core/component`); +const emailBody = new Component('email-body'); + +module.exports = { + name: 'client-welcome', + async serverPrefetch() { + this.client = await this.fetchClient(this.id); + }, + methods: { + fetchClient(id) { + return this.findOneFromDef('client', [id]); + }, + }, + components: { + 'email-body': emailBody.build(), + }, + props: { + id: { + type: Number, + required: true + } + } +}; diff --git a/print/templates/email/worker-welcome/locale/es.yml b/print/templates/email/worker-welcome/locale/es.yml new file mode 100644 index 000000000..769df453e --- /dev/null +++ b/print/templates/email/worker-welcome/locale/es.yml @@ -0,0 +1,7 @@ +subject: Bienvenido a Verdnatura +title: "¡Te damos la bienvenida!" +dearWorker: Estimado trabajador +workerData: 'Bienvenido a Verdnatura SL, este es tu usuario: {0}. Pero primero debes + cambiar tu contraseña. + ' diff --git a/print/templates/email/worker-welcome/sql/client.sql b/print/templates/email/worker-welcome/sql/client.sql new file mode 100644 index 000000000..49e1d4bf6 --- /dev/null +++ b/print/templates/email/worker-welcome/sql/client.sql @@ -0,0 +1,11 @@ +SELECT + c.id, + u.name AS userName, + CONCAT(w.lastName, ' ', w.firstName) salesPersonName, + w.phone AS salesPersonPhone, + CONCAT(wu.name, '@verdnatura.es') AS salesPersonEmail +FROM client c + JOIN account.user u ON u.id = c.id + LEFT JOIN worker w ON w.id = c.salesPersonFk + LEFT JOIN account.user wu ON wu.id = w.userFk +WHERE c.id = ? \ No newline at end of file From 6113ea398d3465424f066d0633741f7576bf1b39 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 14 Nov 2022 15:19:38 +0100 Subject: [PATCH 03/18] feat: worker-welcome --- .../worker-welcome/{client-welcome.html => worker-welcome.html} | 0 .../email/worker-welcome/{client-welcome.js => worker-welcome.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename print/templates/email/worker-welcome/{client-welcome.html => worker-welcome.html} (100%) rename print/templates/email/worker-welcome/{client-welcome.js => worker-welcome.js} (100%) diff --git a/print/templates/email/worker-welcome/client-welcome.html b/print/templates/email/worker-welcome/worker-welcome.html similarity index 100% rename from print/templates/email/worker-welcome/client-welcome.html rename to print/templates/email/worker-welcome/worker-welcome.html diff --git a/print/templates/email/worker-welcome/client-welcome.js b/print/templates/email/worker-welcome/worker-welcome.js similarity index 100% rename from print/templates/email/worker-welcome/client-welcome.js rename to print/templates/email/worker-welcome/worker-welcome.js From 7a7da9508f7dbdfc0fbee318d29fe2c3a8c65afb Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 15 Nov 2022 12:56:30 +0100 Subject: [PATCH 04/18] feat: workerWelcomeEmail --- modules/worker/back/methods/worker/new.js | 156 +++++++++--------- .../back/methods/worker/workerWelcomeEmail.js | 78 +++++++++ .../email/worker-welcome/worker-welcome.html | 1 - 3 files changed, 159 insertions(+), 76 deletions(-) create mode 100644 modules/worker/back/methods/worker/workerWelcomeEmail.js diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js index bdab1335a..a57ca8c21 100644 --- a/modules/worker/back/methods/worker/new.js +++ b/modules/worker/back/methods/worker/new.js @@ -1,5 +1,4 @@ const md5 = require('md5'); -const {Email} = require('vn-print'); module.exports = Self => { Self.remoteMethodCtx('new', { @@ -10,113 +9,113 @@ module.exports = Self => { arg: 'fi', type: 'string', description: `The fi of worker`, - required: true + required: true, }, { arg: 'name', type: 'string', description: `REPLACE!`, - required: true + required: true, }, { arg: 'firstName', type: 'string', description: `REPLACE!`, - required: true + required: true, }, { arg: 'lastNames', type: 'string', description: `REPLACE!`, - required: true + required: true, }, { arg: 'email', type: 'string', description: `REPLACE!`, - required: true + required: true, }, { arg: 'roleFk', type: 'number', description: `REPLACE!`, - required: true + required: true, }, { arg: 'street', type: 'string', description: `REPLACE!`, - required: true + required: true, }, { arg: 'city', type: 'string', description: `REPLACE!`, - required: true + required: true, }, { arg: 'provinceFk', type: 'number', description: `REPLACE!`, - required: true + required: true, }, { arg: 'iban', type: 'string', description: `REPLACE!`, - required: true + required: true, }, { arg: 'bankEntityFk', type: 'number', description: `REPLACE!`, - required: true + required: true, }, { arg: 'companyFk', type: 'number', description: `REPLACE!`, - required: true + required: true, }, { arg: 'postcode', type: 'string', description: `REPLACE!`, - required: true + required: true, }, { arg: 'phone', type: 'string', description: `REPLACE!`, - required: true + required: true, }, { arg: 'code', type: 'string', description: `REPLACE!`, - required: true + required: true, }, { arg: 'bossFk', type: 'number', description: `REPLACE!`, - required: true + required: true, }, { arg: 'birth', type: 'date', description: `REPLACE!`, - required: true - } + required: true, + }, ], returns: { type: 'number', - root: true + root: true, }, http: { path: `/new`, - verb: 'POST' - } + verb: 'POST', + }, }); Self.new = async(ctx, options) => { @@ -126,8 +125,7 @@ module.exports = Self => { let tx; console.log(args); - if (typeof options == 'object') - Object.assign(myOptions, options); + if (typeof options == 'object') Object.assign(myOptions, options); if (!myOptions.transaction) { tx = await Self.beginTransaction({}); @@ -136,26 +134,38 @@ module.exports = Self => { let client; try { - client = await models.Client.findOne({ - where: {fi: args.fi}, - }, myOptions); + client = await models.Client.findOne( + { + where: {fi: args.fi}, + }, + myOptions + ); if (!client) { const nickname = args.firstName.concat(' ', args.lastNames); - const randomPassword = await models.Worker.rawSql('SELECT account.passwordGenerate();'); - const user = await models.Account.create({ - name: args.name, - nickname, - password: md5(randomPassword), - email: args.email, - role: args.role - }, myOptions); + const randomPassword = await models.Worker.rawSql( + 'SELECT account.passwordGenerate();' + ); + const user = await models.Account.create( + { + name: args.name, + nickname, + password: md5(randomPassword), + email: args.email, + role: args.role, + }, + myOptions + ); - await models.UserAccount.create({ - id: user.id - }, myOptions); + await models.UserAccount.create( + { + id: user.id, + }, + myOptions + ); - await models.Worker.rawSql('CALL vn.clientCreate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + await models.Worker.rawSql( + 'CALL vn.clientCreate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [ args.firstName, args.lastNames, @@ -167,31 +177,38 @@ module.exports = Self => { args.companyFk, args.phone, args.email, - user.id - ] - , myOptions); + user.id, + ], + myOptions + ); - const address = await models.Address.create({ - clientFk: user.id, - street: args.street, - city: args.city, - provinceFk: args.provinceFk, - postalCode: args.postalCode, - mobile: args.phone, - nickname: 'TR ' + nickname, - isDefaultAddress: true - }, myOptions); + const address = await models.Address.create( + { + clientFk: user.id, + street: args.street, + city: args.city, + provinceFk: args.provinceFk, + postalCode: args.postalCode, + mobile: args.phone, + nickname: 'TR ' + nickname, + isDefaultAddress: true, + }, + myOptions + ); client = await models.Client.findById(user.id, null, myOptions); - console.log(address.id); - await client.updateAttributes({ - iban: args.iban, - bankEntityFk: args.bankEntityFk, - defaultAddressFk: address.id - }, myOptions); + await client.updateAttributes( + { + iban: args.iban, + bankEntityFk: args.bankEntityFk, + defaultAddressFk: address.id, + }, + myOptions + ); } - await models.Worker.rawSql('CALL vn.workerCreate(?, ?, ?, ?, ?, ?, ?)', + await models.Worker.rawSql( + 'CALL vn.workerCreate(?, ?, ?, ?, ?, ?, ?)', [ args.firstName, args.lastNames, @@ -199,9 +216,10 @@ module.exports = Self => { args.bossFk, client.id, args.fi, - args.birth - ] - , myOptions); + args.birth, + ], + myOptions + ); if (tx) await tx.commit(); } catch (e) { @@ -209,19 +227,7 @@ module.exports = Self => { throw e; } - // TODO: create this email, use client-welcome as template. And view CALL mail_insert in redmine for the body - // TODO: or use same funcionality back/methods/account/recover-password.js - - // TODO: call worerWelcomeEmail, and this is who create the url for change password - - const email = new Email('worker-welcome', { - recipient: args.email, - lang: ctx.req.getLocale() - }); - - await email.send(); - - // return id, and in front use for redirection + await models.Worker.workerWelcomeEmail(client.id); return client.id; }; }; diff --git a/modules/worker/back/methods/worker/workerWelcomeEmail.js b/modules/worker/back/methods/worker/workerWelcomeEmail.js new file mode 100644 index 000000000..7462df34d --- /dev/null +++ b/modules/worker/back/methods/worker/workerWelcomeEmail.js @@ -0,0 +1,78 @@ +const {Email} = require('vn-print'); + +module.exports = Self => { + Self.remoteMethodCtx('workerWelcomeEmail', { + description: + 'Sends the welcome email to the new worker', + accessType: 'WRITE', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'The worker id', + http: {source: 'path'}, + } + ], + returns: { + type: ['object'], + root: true, + }, + http: { + path: '/:id/worker-welcome-email', + verb: 'POST', + }, + }); + + Self.workerWelcomeEmail = async ctx => { + const models = Self.app.models; + const userId = ctx.req.accessToken.userId; + const $t = ctx.req.__; // $translate + const origin = ctx.req.headers.origin; + + const args = Object.assign({}, ctx.args); + const params = { + recipient: args.recipient, + lang: ctx.req.getLocale(), + }; + + delete args.ctx; + for (const param in args) params[param] = args[param]; + + const claim = await models.Claim.findById(args.id, { + fields: ['id', 'clientFk'], + include: { + relation: 'client', + scope: { + fields: ['name', 'salesPersonFk'], + }, + }, + }); + + const message = $t('Claim pickup order sent', { + claimId: args.id, + clientName: claim.client().name, + claimUrl: `${origin}/#!/claim/${args.id}/summary`, + }); + + const salesPersonId = claim.client().salesPersonFk; + if (salesPersonId) + await models.Chat.sendCheckingPresence(ctx, salesPersonId, message); + + await models.ClaimLog.create({ + originFk: args.id, + userFk: userId, + action: 'insert', + description: 'Claim-pickup-order sent', + changedModel: 'Mail', + }); + + const email = new Email('worker-welcome', { + recipient: args.email, + lang: ctx.req.getLocale(), + }); + + await email.send(); + // TODO: or use same funcionality back/methods/account/recover-password.js + }; +}; diff --git a/print/templates/email/worker-welcome/worker-welcome.html b/print/templates/email/worker-welcome/worker-welcome.html index 6aaee6120..f91c9941d 100644 --- a/print/templates/email/worker-welcome/worker-welcome.html +++ b/print/templates/email/worker-welcome/worker-welcome.html @@ -3,7 +3,6 @@

{{ $t('title', [id]) }}

{{ $t('description.dearWorker') }},

-

{{ $t('workerData', this.user.name, this.url) }}

From 7c75eaadce02044fe970a7565fbc7ced641abdbd Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 21 Nov 2022 15:15:25 +0100 Subject: [PATCH 05/18] feat: worker-welcome --- print/templates/email/worker-welcome/sql/client.sql | 11 ----------- print/templates/email/worker-welcome/sql/worker.sql | 7 +++++++ .../email/worker-welcome/worker-welcome.html | 2 +- .../templates/email/worker-welcome/worker-welcome.js | 8 ++++---- 4 files changed, 12 insertions(+), 16 deletions(-) delete mode 100644 print/templates/email/worker-welcome/sql/client.sql create mode 100644 print/templates/email/worker-welcome/sql/worker.sql diff --git a/print/templates/email/worker-welcome/sql/client.sql b/print/templates/email/worker-welcome/sql/client.sql deleted file mode 100644 index 49e1d4bf6..000000000 --- a/print/templates/email/worker-welcome/sql/client.sql +++ /dev/null @@ -1,11 +0,0 @@ -SELECT - c.id, - u.name AS userName, - CONCAT(w.lastName, ' ', w.firstName) salesPersonName, - w.phone AS salesPersonPhone, - CONCAT(wu.name, '@verdnatura.es') AS salesPersonEmail -FROM client c - JOIN account.user u ON u.id = c.id - LEFT JOIN worker w ON w.id = c.salesPersonFk - LEFT JOIN account.user wu ON wu.id = w.userFk -WHERE c.id = ? \ No newline at end of file diff --git a/print/templates/email/worker-welcome/sql/worker.sql b/print/templates/email/worker-welcome/sql/worker.sql new file mode 100644 index 000000000..99377fec9 --- /dev/null +++ b/print/templates/email/worker-welcome/sql/worker.sql @@ -0,0 +1,7 @@ +SELECT + u.id, + u.name AS userName, + e.email +FROM account.user u + LEFT JOIN account.emailUser e ON e.userFk = u.id +WHERE u.id = ?; diff --git a/print/templates/email/worker-welcome/worker-welcome.html b/print/templates/email/worker-welcome/worker-welcome.html index f91c9941d..28e5689f1 100644 --- a/print/templates/email/worker-welcome/worker-welcome.html +++ b/print/templates/email/worker-welcome/worker-welcome.html @@ -3,7 +3,7 @@

{{ $t('title', [id]) }}

{{ $t('description.dearWorker') }},

-

{{ $t('workerData', this.user.name, this.url) }}

+

{{ $t('workerData', this.worker.name, this.url) }}

diff --git a/print/templates/email/worker-welcome/worker-welcome.js b/print/templates/email/worker-welcome/worker-welcome.js index 9fbcf86a6..b9bf2ca28 100755 --- a/print/templates/email/worker-welcome/worker-welcome.js +++ b/print/templates/email/worker-welcome/worker-welcome.js @@ -2,13 +2,13 @@ const Component = require(`vn-print/core/component`); const emailBody = new Component('email-body'); module.exports = { - name: 'client-welcome', + name: 'worker-welcome', async serverPrefetch() { - this.client = await this.fetchClient(this.id); + this.worker = await this.fetchWorker(this.id); }, methods: { - fetchClient(id) { - return this.findOneFromDef('client', [id]); + fetchWorker(id) { + return this.findOneFromDef('worker', [id]); }, }, components: { From f70a9cb78588a139ff37ce115d6b3c7bbdc9857d Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 23 Nov 2022 14:46:25 +0100 Subject: [PATCH 06/18] feat(worker_new): use resetPassword funcionality --- modules/worker/back/methods/worker/new.js | 7 +- .../back/methods/worker/workerWelcomeEmail.js | 78 ------------------- 2 files changed, 6 insertions(+), 79 deletions(-) delete mode 100644 modules/worker/back/methods/worker/workerWelcomeEmail.js diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js index a57ca8c21..7a61434f0 100644 --- a/modules/worker/back/methods/worker/new.js +++ b/modules/worker/back/methods/worker/new.js @@ -227,7 +227,12 @@ module.exports = Self => { throw e; } - await models.Worker.workerWelcomeEmail(client.id); + await models.user.resetPassword({ + email: args.email, + emailTemplate: 'worker-welcome', + id: client.id + }); + return client.id; }; }; diff --git a/modules/worker/back/methods/worker/workerWelcomeEmail.js b/modules/worker/back/methods/worker/workerWelcomeEmail.js deleted file mode 100644 index 7462df34d..000000000 --- a/modules/worker/back/methods/worker/workerWelcomeEmail.js +++ /dev/null @@ -1,78 +0,0 @@ -const {Email} = require('vn-print'); - -module.exports = Self => { - Self.remoteMethodCtx('workerWelcomeEmail', { - description: - 'Sends the welcome email to the new worker', - accessType: 'WRITE', - accepts: [ - { - arg: 'id', - type: 'number', - required: true, - description: 'The worker id', - http: {source: 'path'}, - } - ], - returns: { - type: ['object'], - root: true, - }, - http: { - path: '/:id/worker-welcome-email', - verb: 'POST', - }, - }); - - Self.workerWelcomeEmail = async ctx => { - const models = Self.app.models; - const userId = ctx.req.accessToken.userId; - const $t = ctx.req.__; // $translate - const origin = ctx.req.headers.origin; - - const args = Object.assign({}, ctx.args); - const params = { - recipient: args.recipient, - lang: ctx.req.getLocale(), - }; - - delete args.ctx; - for (const param in args) params[param] = args[param]; - - const claim = await models.Claim.findById(args.id, { - fields: ['id', 'clientFk'], - include: { - relation: 'client', - scope: { - fields: ['name', 'salesPersonFk'], - }, - }, - }); - - const message = $t('Claim pickup order sent', { - claimId: args.id, - clientName: claim.client().name, - claimUrl: `${origin}/#!/claim/${args.id}/summary`, - }); - - const salesPersonId = claim.client().salesPersonFk; - if (salesPersonId) - await models.Chat.sendCheckingPresence(ctx, salesPersonId, message); - - await models.ClaimLog.create({ - originFk: args.id, - userFk: userId, - action: 'insert', - description: 'Claim-pickup-order sent', - changedModel: 'Mail', - }); - - const email = new Email('worker-welcome', { - recipient: args.email, - lang: ctx.req.getLocale(), - }); - - await email.send(); - // TODO: or use same funcionality back/methods/account/recover-password.js - }; -}; From 42adba35387ea784fb115c984198d908ec25181f Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 23 Nov 2022 15:11:46 +0100 Subject: [PATCH 07/18] mail content --- print/templates/email/worker-welcome/locale/es.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/print/templates/email/worker-welcome/locale/es.yml b/print/templates/email/worker-welcome/locale/es.yml index 769df453e..d95f37bd6 100644 --- a/print/templates/email/worker-welcome/locale/es.yml +++ b/print/templates/email/worker-welcome/locale/es.yml @@ -1,7 +1,8 @@ subject: Bienvenido a Verdnatura title: "¡Te damos la bienvenida!" dearWorker: Estimado trabajador -workerData: 'Bienvenido a Verdnatura SL, este es tu usuario: {0}. Pero primero debes - cambiar tu contraseña. - ' +workerData: 'Estos son los datos de tu usuario de Verdnatura. + Usuario: {0}. Haz click aquí para + establecer tu contraseña. + .' From 7822a6cac81b25cd2559cf4e95f01d9f3c8d144e Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 12 Dec 2022 13:48:20 +0100 Subject: [PATCH 08/18] change folder --- db/changes/225001/.gitkeep | 1 - db/changes/{224903 => 225001}/00-aclProfileType.sql | 0 2 files changed, 1 deletion(-) delete mode 100644 db/changes/225001/.gitkeep rename db/changes/{224903 => 225001}/00-aclProfileType.sql (100%) diff --git a/db/changes/225001/.gitkeep b/db/changes/225001/.gitkeep deleted file mode 100644 index 7a4187c02..000000000 --- a/db/changes/225001/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -Delete this file diff --git a/db/changes/224903/00-aclProfileType.sql b/db/changes/225001/00-aclProfileType.sql similarity index 100% rename from db/changes/224903/00-aclProfileType.sql rename to db/changes/225001/00-aclProfileType.sql From bb944f9fee9b0a4928a03068b20e3006a6fd6556 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 12 Dec 2022 15:05:49 +0100 Subject: [PATCH 09/18] feat(newWorker): use worker-welcome --- front/salix/components/app/app.js | 2 +- modules/worker/back/methods/worker/new.js | 5 +++-- modules/worker/front/create/index.js | 3 +-- modules/worker/front/index/locale/es.yml | 1 + print/templates/email/email-verify/email-verify.js | 2 +- print/templates/email/recover-password/recover-password.js | 2 +- print/templates/email/worker-welcome/locale/es.yml | 4 ++-- print/templates/email/worker-welcome/sql/worker.sql | 2 +- print/templates/email/worker-welcome/worker-welcome.html | 4 ++-- print/templates/email/worker-welcome/worker-welcome.js | 5 +++++ 10 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 modules/worker/front/index/locale/es.yml diff --git a/front/salix/components/app/app.js b/front/salix/components/app/app.js index 20f0ad969..91a8d2215 100644 --- a/front/salix/components/app/app.js +++ b/front/salix/components/app/app.js @@ -21,7 +21,7 @@ export default class App extends Component { get showLayout() { const state = this.$state.current.name || this.$location.$$path.substring(1).replace('/', '.'); - const outLayout = ['login', 'recoverPassword', 'resetPassword']; + const outLayout = ['login', 'recoverPassword', 'resetPassword', 'reset-password']; return state && !outLayout.some(ol => ol == state); } diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js index 7a61434f0..97fdc1033 100644 --- a/modules/worker/back/methods/worker/new.js +++ b/modules/worker/back/methods/worker/new.js @@ -124,7 +124,7 @@ module.exports = Self => { const args = ctx.args; let tx; - console.log(args); + if (typeof options == 'object') Object.assign(myOptions, options); if (!myOptions.transaction) { @@ -224,6 +224,7 @@ module.exports = Self => { if (tx) await tx.commit(); } catch (e) { if (tx) await tx.rollback(); + console.log(e); throw e; } @@ -233,6 +234,6 @@ module.exports = Self => { id: client.id }); - return client.id; + return {id: client.id}; }; }; diff --git a/modules/worker/front/create/index.js b/modules/worker/front/create/index.js index a068b2006..fdc02361d 100644 --- a/modules/worker/front/create/index.js +++ b/modules/worker/front/create/index.js @@ -11,8 +11,7 @@ export default class Controller extends Section { onSubmit() { return this.$.watcher.submit().then(json => { - this.$state.go('client.card.basicData', {id: json.data.id}); - this.$http.get(`Clients/${this.client.id}/checkDuplicatedData`); + this.$state.go('worker.card.basicData', {id: json.data.id}); }); } diff --git a/modules/worker/front/index/locale/es.yml b/modules/worker/front/index/locale/es.yml new file mode 100644 index 000000000..df6383273 --- /dev/null +++ b/modules/worker/front/index/locale/es.yml @@ -0,0 +1 @@ +New worker: Nuevo trabajador diff --git a/print/templates/email/email-verify/email-verify.js b/print/templates/email/email-verify/email-verify.js index 7f0b80a13..4f2b29266 100755 --- a/print/templates/email/email-verify/email-verify.js +++ b/print/templates/email/email-verify/email-verify.js @@ -10,7 +10,7 @@ module.exports = { }, props: { url: { - type: [String], + type: String, required: true } } diff --git a/print/templates/email/recover-password/recover-password.js b/print/templates/email/recover-password/recover-password.js index b589411a9..d8448f370 100755 --- a/print/templates/email/recover-password/recover-password.js +++ b/print/templates/email/recover-password/recover-password.js @@ -10,7 +10,7 @@ module.exports = { }, props: { url: { - type: [String], + type: String, required: true } } diff --git a/print/templates/email/worker-welcome/locale/es.yml b/print/templates/email/worker-welcome/locale/es.yml index d95f37bd6..d53a4e1f0 100644 --- a/print/templates/email/worker-welcome/locale/es.yml +++ b/print/templates/email/worker-welcome/locale/es.yml @@ -3,6 +3,6 @@ title: "¡Te damos la bienvenida!" dearWorker: Estimado trabajador workerData: 'Estos son los datos de tu usuario de Verdnatura. Usuario: {0}. Haz click aquí para - establecer tu contraseña. + establecer tu contraseña .' diff --git a/print/templates/email/worker-welcome/sql/worker.sql b/print/templates/email/worker-welcome/sql/worker.sql index 99377fec9..f75d135d9 100644 --- a/print/templates/email/worker-welcome/sql/worker.sql +++ b/print/templates/email/worker-welcome/sql/worker.sql @@ -1,6 +1,6 @@ SELECT u.id, - u.name AS userName, + u.name, e.email FROM account.user u LEFT JOIN account.emailUser e ON e.userFk = u.id diff --git a/print/templates/email/worker-welcome/worker-welcome.html b/print/templates/email/worker-welcome/worker-welcome.html index 28e5689f1..fbb05d149 100644 --- a/print/templates/email/worker-welcome/worker-welcome.html +++ b/print/templates/email/worker-welcome/worker-welcome.html @@ -2,8 +2,8 @@

{{ $t('title', [id]) }}

-

{{ $t('description.dearWorker') }},

-

{{ $t('workerData', this.worker.name, this.url) }}

+

{{ $t('dearWorker') }},

+

diff --git a/print/templates/email/worker-welcome/worker-welcome.js b/print/templates/email/worker-welcome/worker-welcome.js index b9bf2ca28..3fc9b4706 100755 --- a/print/templates/email/worker-welcome/worker-welcome.js +++ b/print/templates/email/worker-welcome/worker-welcome.js @@ -5,6 +5,7 @@ module.exports = { name: 'worker-welcome', async serverPrefetch() { this.worker = await this.fetchWorker(this.id); + console.log(this.url); }, methods: { fetchWorker(id) { @@ -18,6 +19,10 @@ module.exports = { id: { type: Number, required: true + }, + url: { + type: String, + required: true } } }; From 156f2b9129c02b8ed928f72007b05d977625573a Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 14 Dec 2022 15:03:55 +0100 Subject: [PATCH 10/18] feat: handle errors and autogenerate user and code --- loopback/locale/es.json | 9 ++-- modules/worker/back/methods/worker/new.js | 54 ++++++++++++++--------- modules/worker/front/create/index.html | 9 ++-- modules/worker/front/create/index.js | 14 ++++++ modules/worker/front/create/locale/es.yml | 20 ++++----- 5 files changed, 69 insertions(+), 37 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 932dfe98f..41dfff73a 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -247,7 +247,10 @@ "Empty data source": "Origen de datos vacio", "Email verify": "Correo de verificación", "Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment", - "Receipt's bank was not found": "No se encontró el banco del recibo", - "This receipt was not compensated": "Este recibo no ha sido compensado", - "Client's email was not found": "No se encontró el email del cliente" + "Receipt's bank was not found": "No se encontró el banco del recibo", + "This receipt was not compensated": "Este recibo no ha sido compensado", + "Client's email was not found": "No se encontró el email del cliente", + "This worker code already exists": "Este codigo de trabajador ya existe", + "This personal mail already exists": "Este correo personal ya existe", + "This worker already exists": "Este trabajador ya existe" } diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js index 97fdc1033..07a091693 100644 --- a/modules/worker/back/methods/worker/new.js +++ b/modules/worker/back/methods/worker/new.js @@ -1,4 +1,5 @@ const md5 = require('md5'); +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('new', { @@ -8,103 +9,103 @@ module.exports = Self => { { arg: 'fi', type: 'string', - description: `The fi of worker`, + description: `The worker fi`, required: true, }, { arg: 'name', type: 'string', - description: `REPLACE!`, + description: `The user name`, required: true, }, { arg: 'firstName', type: 'string', - description: `REPLACE!`, + description: `The worker firstname`, required: true, }, { arg: 'lastNames', type: 'string', - description: `REPLACE!`, + description: `The worker lastnames`, required: true, }, { arg: 'email', type: 'string', - description: `REPLACE!`, + description: `The worker email`, required: true, }, { arg: 'roleFk', type: 'number', - description: `REPLACE!`, + description: `The worker role`, required: true, }, { arg: 'street', type: 'string', - description: `REPLACE!`, + description: `The worker address`, required: true, }, { arg: 'city', type: 'string', - description: `REPLACE!`, + description: `The worker city`, required: true, }, { arg: 'provinceFk', type: 'number', - description: `REPLACE!`, + description: `The worker province`, required: true, }, { arg: 'iban', type: 'string', - description: `REPLACE!`, + description: `The worker iban`, required: true, }, { arg: 'bankEntityFk', type: 'number', - description: `REPLACE!`, + description: `The worker bank entity`, required: true, }, { arg: 'companyFk', type: 'number', - description: `REPLACE!`, + description: `The worker company`, required: true, }, { arg: 'postcode', type: 'string', - description: `REPLACE!`, + description: `The worker postcode`, required: true, }, { arg: 'phone', type: 'string', - description: `REPLACE!`, + description: `The worker phone`, required: true, }, { arg: 'code', type: 'string', - description: `REPLACE!`, + description: `The worker code`, required: true, }, { arg: 'bossFk', type: 'number', - description: `REPLACE!`, + description: `The worker boss`, required: true, }, { arg: 'birth', type: 'date', - description: `REPLACE!`, + description: `The worker birth`, required: true, }, ], @@ -152,7 +153,7 @@ module.exports = Self => { nickname, password: md5(randomPassword), email: args.email, - role: args.role, + role: args.roleFk, }, myOptions ); @@ -222,10 +223,21 @@ module.exports = Self => { ); if (tx) await tx.commit(); - } catch (e) { + } catch (err) { if (tx) await tx.rollback(); - console.log(e); - throw e; + const code = err.code; + const message = err.sqlMessage; + + if (code === 'ER_DUP_ENTRY' && message.includes(`for key 'mail'`)) + throw new UserError(`This personal mail already exists`); + + if (code === 'ER_DUP_ENTRY' && message.includes(`CodigoTrabajador_UNIQUE`)) + throw new UserError(`This worker code already exists`); + + if (code === 'ER_DUP_ENTRY' && message.includes(`PRIMARY`)) + throw new UserError(`This worker already exists`); + + throw err; } await models.user.resetPassword({ diff --git a/modules/worker/front/create/index.html b/modules/worker/front/create/index.html index 58b4da060..a86a4e899 100644 --- a/modules/worker/front/create/index.html +++ b/modules/worker/front/create/index.html @@ -13,11 +13,13 @@ label="Firstname" ng-model="$ctrl.worker.firstName" rule + on-change="$ctrl.generateCodeUser()" vn-focus> @@ -38,6 +40,8 @@ vn-one label="Code" ng-model="$ctrl.worker.code" + maxLength="3" + on-change="$ctrl.worker.code = $ctrl.worker.code.toUpperCase()" rule> + rule> - - Puede guardar varios correos electrónicos encadenándolos mediante comas - sin espacios, ejemplo: user@dominio.com, user2@dominio.com siendo el primer - correo electrónico el principal -The type of business must be filled in basic data: El tipo de negocio debe estar rellenado en datos básicos Access permission: Permiso de acceso From aa5cfde1ae85e01be945fa6e5d92e44d42c6773f Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 2 Jan 2023 14:52:03 +0100 Subject: [PATCH 11/18] test(worker_new): add back tests --- CHANGELOG.md | 1 + db/dump/fixtures.sql | 14 +- .../components/reset-password/locale/es.yml | 2 +- modules/worker/back/methods/worker/new.js | 27 +++- .../back/methods/worker/specs/new.spec.js | 140 ++++++++++++++++++ modules/worker/front/create/index.js | 20 +++ .../email/worker-welcome/worker-welcome.js | 1 - 7 files changed, 188 insertions(+), 17 deletions(-) create mode 100644 modules/worker/back/methods/worker/specs/new.spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index bafedc760..897774716 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - [General](Inicio) Permite recuperar la contraseña +- [Trabajadores](Nuevo trabajador) Nueva sección ### Changed diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 03a0f8b50..933651f06 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -934,10 +934,10 @@ INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `freightItemFk`, (7, 2, 4, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), 1, 18, NULL, 94, NULL,NULL), (8, 3, 5, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), 1, 18, NULL, 94, 1, NULL), (9, 3, 6, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, NULL, 94, 2, NULL), - (10, 7, 7, 71, NOW(), 1, 18, NULL, 94, 3, NULL), - (11, 7, 8, 71, NOW(), 1, 18, NULL, 94, 3, NULL), - (12, 7, 9, 71, NOW(), 1, 18, NULL, 94, 3, NULL), - (13, 1, 10,71, NOW(), 1, 18, NULL, 94, 3, NULL); + (10, 7, 7, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), + (11, 7, 8, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), + (12, 7, 9, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), + (13, 1, 10,71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL); INSERT INTO `vn`.`expeditionState`(`id`, `created`, `expeditionFk`, `typeFk`, `userFk`) @@ -1910,7 +1910,7 @@ DROP TEMPORARY TABLE IF EXISTS tmp.worker; CREATE TEMPORARY TABLE tmp.worker (PRIMARY KEY (id)) ENGINE = MEMORY - SELECT w.id, w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR)), '-12-25'), CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL +1 YEAR)), '-12-25'), CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` + SELECT w.id, w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 YEAR)), '-12-25'), CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL +1 YEAR)), '-12-25'), CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` FROM `vn`.`worker` `w`; INSERT INTO `vn`.`business`(`id`, `workerFk`, `companyCodeFk`, `started`, `ended`, `workerBusiness`, `reasonEndFk`, `notes`, `departmentFk`, `workerBusinessProfessionalCategoryFk`, `calendarTypeFk`, `isHourlyLabor`, `workerBusinessAgreementFk`, `workcenterFk`) @@ -1920,7 +1920,7 @@ DROP TEMPORARY TABLE IF EXISTS tmp.worker; CREATE TEMPORARY TABLE tmp.worker (PRIMARY KEY (id)) ENGINE = MEMORY - SELECT '1111' as 'id', w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL -2 YEAR)), '-12-25'), CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR)), '-12-24'), CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` + SELECT '1111' as 'id', w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -2 YEAR)), '-12-25'), CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 YEAR)), '-12-24'), CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` FROM `vn`.`worker` `w` WHERE `w`.`id` = 1109; @@ -2633,7 +2633,7 @@ INSERT INTO `vn`.`machineWorker` (`workerFk`, `machineFk`, `inTimed`, `outTimed` INSERT INTO `vn`.`zoneExclusion` (`id`, `zoneFk`, `dated`, `created`, `userFk`) VALUES - (1, 1, DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=7, 7, 14) - DAYOFWEEK(util.VN_CURDATE())) DAY), util.VN_CURDATE(), 100), + (1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL (IF(DAYOFWEEK(util.VN_CURDATE())<=7, 7, 14) - DAYOFWEEK(util.VN_CURDATE())) DAY), util.VN_CURDATE(), 100), (2, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL (IF(DAYOFWEEK(util.VN_CURDATE())<=8, 8, 15) - DAYOFWEEK(util.VN_CURDATE())) DAY), util.VN_CURDATE(), 100); INSERT INTO `vn`.`zoneExclusionGeo` (`zoneExclusionFk`, `geoFk`) diff --git a/front/salix/components/reset-password/locale/es.yml b/front/salix/components/reset-password/locale/es.yml index 0771d5dc3..30893a152 100644 --- a/front/salix/components/reset-password/locale/es.yml +++ b/front/salix/components/reset-password/locale/es.yml @@ -1,6 +1,6 @@ Reset password: Restrablecer contraseña New password: Nueva contraseña -Repeat password: Repetir contraseñaç +Repeat password: Repetir contraseña Password changed!: ¡Contraseña cambiada! Password requirements: > La contraseña debe tener al menos {{ length }} caracteres de longitud, diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js index 07a091693..b6da3301a 100644 --- a/modules/worker/back/methods/worker/new.js +++ b/modules/worker/back/methods/worker/new.js @@ -1,4 +1,3 @@ -const md5 = require('md5'); const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { @@ -108,6 +107,12 @@ module.exports = Self => { description: `The worker birth`, required: true, }, + { + arg: 'profileTypeFk', + type: 'number', + description: `The worker profile type ¿DELETE?`, + required: true, + } ], returns: { type: 'number', @@ -134,6 +139,7 @@ module.exports = Self => { } let client; + try { client = await models.Client.findOne( { @@ -144,14 +150,15 @@ module.exports = Self => { if (!client) { const nickname = args.firstName.concat(' ', args.lastNames); - const randomPassword = await models.Worker.rawSql( - 'SELECT account.passwordGenerate();' + const [randomPassword] = await models.Worker.rawSql( + 'SELECT account.passwordGenerate() as password;' ); + const user = await models.Account.create( { name: args.name, nickname, - password: md5(randomPassword), + password: randomPassword.password, email: args.email, role: args.roleFk, }, @@ -208,6 +215,10 @@ module.exports = Self => { myOptions ); } + + const user = await models.Account.findById(client.id, null, myOptions); + await user.updateAttribute('email', args.email, myOptions); + await models.Worker.rawSql( 'CALL vn.workerCreate(?, ?, ?, ?, ?, ?, ?)', [ @@ -223,10 +234,10 @@ module.exports = Self => { ); if (tx) await tx.commit(); - } catch (err) { + } catch (error) { if (tx) await tx.rollback(); - const code = err.code; - const message = err.sqlMessage; + const code = error.code; + const message = error.sqlMessage; if (code === 'ER_DUP_ENTRY' && message.includes(`for key 'mail'`)) throw new UserError(`This personal mail already exists`); @@ -237,7 +248,7 @@ module.exports = Self => { if (code === 'ER_DUP_ENTRY' && message.includes(`PRIMARY`)) throw new UserError(`This worker already exists`); - throw err; + throw error; } await models.user.resetPassword({ diff --git a/modules/worker/back/methods/worker/specs/new.spec.js b/modules/worker/back/methods/worker/specs/new.spec.js new file mode 100644 index 000000000..2cb8bebef --- /dev/null +++ b/modules/worker/back/methods/worker/specs/new.spec.js @@ -0,0 +1,140 @@ +const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); + +describe('Worker new', () => { + beforeAll(async() => { + const activeCtx = { + accessToken: {userId: 9}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + + const employeeId = 1; + const defaultWorker = { + fi: '78457139E', + name: 'defaultWorker', + firstName: 'default', + lastNames: 'worker', + email: 'defaultWorker@mydomain.com', + roleFk: 1, + street: 'S/ defaultWorkerStreet', + city: 'defaultWorkerCity', + provinceFk: 1, + iban: 'ES8304879798578129532677', + bankEntityFk: 128, + companyFk: 442, + postcode: '46680', + phone: '633342693', + code: 'DWW', + bossFk: 9, + birth: '2022-12-11T23:00:00.000Z' + }; + + it('should return error if personal mail already exists', async() => { + const user = await models.Account.findById(employeeId, {fields: ['email']}); + + const tx = await models.Worker.beginTransaction({}); + + let error; + try { + const options = {transaction: tx}; + const ctx = { + args: Object.assign({}, defaultWorker, {email: user.email}) + }; + + await models.Worker.new(ctx, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual('This personal mail already exists'); + }); + + it('should return error if worker code already exists', async() => { + const worker = await models.Worker.findById(employeeId, {fields: ['code']}); + + const tx = await models.Worker.beginTransaction({}); + + let error; + try { + const options = {transaction: tx}; + const ctx = { + args: Object.assign({}, defaultWorker, {code: worker.code}) + }; + + await models.Worker.new(ctx, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual('This worker code already exists'); + }); + + it('should return error if worker already exists', async() => { + const worker = await models.Client.findById(employeeId, {fields: ['fi']}); + + const tx = await models.Worker.beginTransaction({}); + + let error; + try { + const options = {transaction: tx}; + const ctx = { + args: Object.assign({}, defaultWorker, {fi: worker.fi}) + }; + await models.Worker.new(ctx, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.message).toEqual('This worker already exists'); + }); + + it('should create a new worker', async() => { + const newWorker = await models.Worker.new({args: defaultWorker}); + + await models.Worker.destroyById(newWorker.id); + await models.Address.destroyAll({clientFk: newWorker.id}); + await models.Mandate.destroyAll({clientFk: newWorker.id}); + await models.Client.destroyById(newWorker.id); + await models.Account.destroyById(newWorker.id); + + expect(newWorker.id).toBeDefined(); + }); + + it('should create a new worker in client', async() => { + const bruceWayneId = 1101; + const client = await models.Client.findById(bruceWayneId, {fields: ['fi', 'email']}); + + const newWorkerData = { + args: Object.assign( + {}, + defaultWorker, + { + fi: client.fi, + email: client.email + }) + }; + const newWorker = await models.Worker.new(newWorkerData); + + await models.Worker.destroyById(newWorker.id); + + expect(newWorker.id).toEqual(bruceWayneId); + }); +}); diff --git a/modules/worker/front/create/index.js b/modules/worker/front/create/index.js index 3314a4b10..b09fde94f 100644 --- a/modules/worker/front/create/index.js +++ b/modules/worker/front/create/index.js @@ -7,6 +7,26 @@ export default class Controller extends Section { this.$http.get('NewWorkerConfigs/findOne').then(res => { return this.worker = Object.assign({}, res.data); }); + // DELETE + this.worker = { + fi: '73226971P', + name: 'ASDASD', + firstName: 'Test', + lastNames: 'Test', + email: 'developer4@mydomain.com', + roleFk: 1, + street: 'S/ ', + city: 'asd', + provinceFk: 1, + iban: 'ES2420386579855387888566', + bankEntityFk: 128, + companyFk: 442, + postcode: 'asd', + phone: '633342693', + code: 'ASD', + bossFk: 34, + birth: '2022-12-11T23:00:00.000Z' + }; } onSubmit() { diff --git a/print/templates/email/worker-welcome/worker-welcome.js b/print/templates/email/worker-welcome/worker-welcome.js index 3fc9b4706..043a172a1 100755 --- a/print/templates/email/worker-welcome/worker-welcome.js +++ b/print/templates/email/worker-welcome/worker-welcome.js @@ -5,7 +5,6 @@ module.exports = { name: 'worker-welcome', async serverPrefetch() { this.worker = await this.fetchWorker(this.id); - console.log(this.url); }, methods: { fetchWorker(id) { From 46c3d87dabce836faf4a21003d6a9ac9d6551493 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 3 Jan 2023 08:09:46 +0100 Subject: [PATCH 12/18] feat(worker_create): add vn-acl --- modules/worker/front/index/index.html | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/modules/worker/front/index/index.html b/modules/worker/front/index/index.html index b48a84854..7044ca551 100644 --- a/modules/worker/front/index/index.html +++ b/modules/worker/front/index/index.html @@ -6,23 +6,23 @@ class="vn-w-sm"> - @@ -52,4 +54,4 @@ -
\ No newline at end of file + From ef437f2feec1209691e1f365c3a394ac6008ea00 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 3 Jan 2023 14:50:29 +0100 Subject: [PATCH 13/18] test: e2e and backTest --- .../{225001 => 230201}/00-aclProfileType.sql | 25 +++++++ db/dump/fixtures.sql | 26 +++---- e2e/helpers/selectors.js | 20 ++++++ e2e/helpers/tests.js | 26 +++---- e2e/paths/03-worker/06_create.spec.js | 72 +++++++++++++++++++ modules/worker/front/create/index.html | 30 ++++---- modules/worker/front/create/index.js | 41 +++++++---- 7 files changed, 186 insertions(+), 54 deletions(-) rename db/changes/{225001 => 230201}/00-aclProfileType.sql (54%) create mode 100644 e2e/paths/03-worker/06_create.spec.js diff --git a/db/changes/225001/00-aclProfileType.sql b/db/changes/230201/00-aclProfileType.sql similarity index 54% rename from db/changes/225001/00-aclProfileType.sql rename to db/changes/230201/00-aclProfileType.sql index 638b3d580..cae7166c9 100644 --- a/db/changes/225001/00-aclProfileType.sql +++ b/db/changes/230201/00-aclProfileType.sql @@ -16,3 +16,28 @@ CREATE TABLE `vn`.`newWorkerConfig` ( CONSTRAINT `newWorkerConfig_profileType_fk` FOREIGN KEY (`profileTypeFk`) REFERENCES `vn`.`profileType` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `newWorkerConfig_role_fk` FOREIGN KEY (`roleFk`) REFERENCES `account`.`role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ); + +UPDATE `salix`.`ACL` +SET accessType='READ' +WHERE model='Worker' + AND property='*' + AND accessType='*' + AND permission='ALLOW' + AND principalType='ROLE' + AND principalId='employee'; + + +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('Worker', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'hr'), + ('Worker', 'createAbsence', '*', 'ALLOW', 'ROLE', 'employee'), + ('Worker', 'updateAbsence', '*', 'ALLOW', 'ROLE', 'employee'), + ('Worker', 'deleteAbsence', '*', 'ALLOW', 'ROLE', 'employee'), + ('Worker', 'new', 'WRITE', 'ALLOW', 'ROLE', 'hr'), + ('Role', '*', 'READ', 'ALLOW', 'ROLE', 'hr'); + +/* +INSERT INTO `vn`.`newWorkerConfig` (`id`, `street`, `provinceFk`, `companyFk`, `profileTypeFk`, `roleFk`) + VALUES + (1, 'C/ ', 57, 442, 1, 1); +*/ diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 90cc19d01..8f1648048 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -934,10 +934,10 @@ INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `freightItemFk`, (7, 2, 4, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH), 1, 18, NULL, 94, NULL,NULL), (8, 3, 5, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH), 1, 18, NULL, 94, 1, NULL), (9, 3, 6, 71, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 18, NULL, 94, 2, NULL), - (10, 7, 7, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), - (11, 7, 8, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), - (12, 7, 9, 71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL), - (13, 1, 10,71, util.VN_NOW(), 1, 18, NULL, 94, 3, NULL); + (10, 7, 7, 71, NOW(), 1, 18, NULL, 94, 3, NULL), + (11, 7, 8, 71, NOW(), 1, 18, NULL, 94, 3, NULL), + (12, 7, 9, 71, NOW(), 1, 18, NULL, 94, 3, NULL), + (13, 1, 10,71, NOW(), 1, 18, NULL, 94, 3, NULL); INSERT INTO `vn`.`expeditionState`(`id`, `created`, `expeditionFk`, `typeFk`, `userFk`) @@ -1910,7 +1910,7 @@ DROP TEMPORARY TABLE IF EXISTS tmp.worker; CREATE TEMPORARY TABLE tmp.worker (PRIMARY KEY (id)) ENGINE = MEMORY - SELECT w.id, w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 YEAR)), '-12-25'), CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL +1 YEAR)), '-12-25'), CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` + SELECT w.id, w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR)), '-12-25'), CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL +1 YEAR)), '-12-25'), CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` FROM `vn`.`worker` `w`; INSERT INTO `vn`.`business`(`id`, `workerFk`, `companyCodeFk`, `started`, `ended`, `workerBusiness`, `reasonEndFk`, `notes`, `departmentFk`, `workerBusinessProfessionalCategoryFk`, `calendarTypeFk`, `isHourlyLabor`, `workerBusinessAgreementFk`, `workcenterFk`) @@ -1920,7 +1920,7 @@ DROP TEMPORARY TABLE IF EXISTS tmp.worker; CREATE TEMPORARY TABLE tmp.worker (PRIMARY KEY (id)) ENGINE = MEMORY - SELECT '1111' as 'id', w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -2 YEAR)), '-12-25'), CONCAT(YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 YEAR)), '-12-24'), CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` + SELECT '1111' as 'id', w.id as `workerFk`, 'VNL', CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL -2 YEAR)), '-12-25'), CONCAT(YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR)), '-12-24'), CONCAT('E-46-', RPAD(CONCAT(w.id, 9), 8, w.id)), NULL as `notes`, NULL as `departmentFk`, 23, 1 as `workerBusinessProfessionalCategoryFk`, 1 as `calendarTypeFk`, 1 as `isHourlyLabor`, 1 as `workerBusinessAgreementFk`, 1 as `workcenterFk` FROM `vn`.`worker` `w` WHERE `w`.`id` = 1109; @@ -2741,13 +2741,6 @@ INSERT INTO `vn`.`ticketLog` (`originFk`, userFk, `action`, changedModel, oldIns (7, 18, 'update', 'Sale', '{"price":3}', '{"price":5}', 1, NULL), (7, 18, 'update', NULL, NULL, NULL, NULL, "Cambio cantidad Melee weapon heavy shield 1x0.5m de '5' a '10'"); -INSERT INTO `vn`.`profileType` (`id`, `name`) - VALUES - (1, 'working'); - -INSERT INTO `vn`.`newWorkerConfig` (`id`, `street`, `provinceFk`, `companyFk`, `profileTypeFk`, `roleFk`) - VALUES - (1, 'S/ ', 1, 442, 1, 1); INSERT INTO `vn`.`osTicketConfig` (`id`, `host`, `user`, `password`, `oldStatus`, `newStatusId`, `day`, `comment`, `hostDb`, `userDb`, `passwordDb`, `portDb`, `responseType`, `fromEmailId`, `replyTo`) VALUES @@ -2758,6 +2751,13 @@ INSERT INTO `vn`.`mdbApp` (`app`, `baselineBranchFk`, `userFk`, `locked`) ('foo', 'master', NULL, NULL), ('bar', 'test', 9, util.VN_NOW()); +INSERT INTO `vn`.`profileType` (`id`, `name`) + VALUES + (1, 'working'); + +INSERT INTO `vn`.`newWorkerConfig` (`id`, `street`, `provinceFk`, `companyFk`, `profileTypeFk`, `roleFk`) + VALUES + (1, 'S/ ', 1, 442, 1, 1); INSERT INTO `salix`.`url` (`appName`, `environment`, `url`) VALUES diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index e1792ea7b..134e41796 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -964,6 +964,7 @@ export default { confirmButton: '.vn-confirm.shown button[response="accept"]' }, workerSummary: { + summaryIcon: 'vn-worker-descriptor a[title="Go to module summary"]', header: 'vn-worker-summary h5', id: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(3) > section > span', email: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(4) > section > span', @@ -1016,6 +1017,25 @@ export default { furlough: 'vn-worker-calendar > vn-side-menu [name="absenceTypes"] > vn-chip:nth-child(4)', halfFurlough: 'vn-worker-calendar > vn-side-menu [name="absenceTypes"] > vn-chip:nth-child(5)', }, + workerCreate: { + newWorkerButton: 'vn-worker-index a[ui-sref="worker.create"]', + firstname: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.firstName"]', + lastname: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.lastNames"]', + birth: 'vn-worker-create vn-date-picker[ng-model="$ctrl.worker.birth"]', + fi: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.fi"]', + code: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.code"]', + phone: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.phone"]', + city: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.city"]', + postcode: 'vn-worker-create vn-datalist[ng-model="$ctrl.worker.postcode"]', + street: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.street"]', + user: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.name"]', + email: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.email"]', + boss: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bossFk"]', + role: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.roleFk"]', + iban: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.iban"]', + switft: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bankEntityFk"]', + createButton: 'vn-worker-create vn-submit[label="Create"]', + }, invoiceOutIndex: { topbarSearch: 'vn-searchbar', searchResult: 'vn-invoice-out-index vn-card > vn-table > div > vn-tbody > a.vn-tr', diff --git a/e2e/helpers/tests.js b/e2e/helpers/tests.js index aac9963dd..9ac616011 100644 --- a/e2e/helpers/tests.js +++ b/e2e/helpers/tests.js @@ -25,20 +25,20 @@ async function test() { const jasmine = new Jasmine(); const specFiles = [ - `./e2e/paths/01*/*[sS]pec.js`, - `./e2e/paths/02*/*[sS]pec.js`, + // `./e2e/paths/01*/*[sS]pec.js`, + // `./e2e/paths/02*/*[sS]pec.js`, `./e2e/paths/03*/*[sS]pec.js`, - `./e2e/paths/04*/*[sS]pec.js`, - `./e2e/paths/05*/*[sS]pec.js`, - `./e2e/paths/06*/*[sS]pec.js`, - `./e2e/paths/07*/*[sS]pec.js`, - `./e2e/paths/08*/*[sS]pec.js`, - `./e2e/paths/09*/*[sS]pec.js`, - `./e2e/paths/10*/*[sS]pec.js`, - `./e2e/paths/11*/*[sS]pec.js`, - `./e2e/paths/12*/*[sS]pec.js`, - `./e2e/paths/13*/*[sS]pec.js`, - `./e2e/paths/**/*[sS]pec.js` + // `./e2e/paths/04*/*[sS]pec.js`, + // `./e2e/paths/05*/*[sS]pec.js`, + // `./e2e/paths/06*/*[sS]pec.js`, + // `./e2e/paths/07*/*[sS]pec.js`, + // `./e2e/paths/08*/*[sS]pec.js`, + // `./e2e/paths/09*/*[sS]pec.js`, + // `./e2e/paths/10*/*[sS]pec.js`, + // `./e2e/paths/11*/*[sS]pec.js`, + // `./e2e/paths/12*/*[sS]pec.js`, + // `./e2e/paths/13*/*[sS]pec.js`, + // `./e2e/paths/**/*[sS]pec.js` ]; jasmine.loadConfig({ diff --git a/e2e/paths/03-worker/06_create.spec.js b/e2e/paths/03-worker/06_create.spec.js new file mode 100644 index 000000000..b93dace88 --- /dev/null +++ b/e2e/paths/03-worker/06_create.spec.js @@ -0,0 +1,72 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +xdescribe('Worker calendar path', () => { + let browser; + let page; + let newWorker; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('hr', 'worker'); + await page.waitToClick(selectors.workerCreate.newWorkerButton); + await page.waitForState('worker.create'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should insert default data', async() => { + await page.write(selectors.workerCreate.firstname, 'Victor'); + await page.write(selectors.workerCreate.lastname, 'Von Doom'); + await page.write(selectors.workerCreate.fi, '78457139E'); + await page.write(selectors.workerCreate.phone, '12356789'); + await page.write(selectors.workerCreate.postcode, '46680'); + await page.write(selectors.workerCreate.street, 'Doomstadt'); + await page.write(selectors.workerCreate.email, 'doctorDoom@marvel.com'); + await page.write(selectors.workerCreate.iban, 'ES9121000418450200051332'); + await page.autocompleteSearch(selectors.workerCreate.switft, 'BBKKESMMMMM'); + }); + + it('should check for autocompleted worker code and worker user name', async() => { + const workerCode = await page + .waitToGetProperty(selectors.workerCreate.code, 'value'); + + newWorker = await page + .waitToGetProperty(selectors.workerCreate.user, 'value'); + + expect(workerCode).toEqual('VVD'); + expect(newWorker).toContain('victorvd'); + }); + + it('should fail if necessary data is void', async() => { + await page.waitToClick(selectors.workerCreate.createButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('is a required argument'); + }); + + it('should create a new worker and go to worker basic data', async() => { + await page.pickDate(selectors.workerCreate.birth, new Date(1962, 8, 5)); + await page.autocompleteSearch(selectors.workerCreate.role, 'Jefe de personal de reparto'); + await page.autocompleteSearch(selectors.workerCreate.boss, 'deliveryBoss'); + await page.waitToClick(selectors.workerCreate.createButton); + const message = await page.waitForSnackbar(); + await page.waitForState('worker.card.basicData'); + + expect(message.text).toContain('Data saved!'); + }); + + xit('rollback', async() => { + await page.loginAndModule('sysadmin', 'account'); + await page.accessToSearchResult(newWorker); + await page.accessToSection('account.card.summary'); + await page.waitToClick(selectors.accountDescriptor.menuButton); + await page.waitToClick(selectors.accountDescriptor.deleteAccount); + await page.waitToClick(selectors.accountDescriptor.acceptButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('User removed'); + }); +}); diff --git a/modules/worker/front/create/index.html b/modules/worker/front/create/index.html index a86a4e899..c09930b80 100644 --- a/modules/worker/front/create/index.html +++ b/modules/worker/front/create/index.html @@ -62,21 +62,6 @@ rule> {{name}} ({{country.country}}) - - - {{name}}, {{province.name}} - ({{province.country.country}}) - - - - + + + + + {{name}}, {{province.name}} + ({{province.country.country}}) + + { - return this.worker = Object.assign({}, res.data); - }); + // this.$http.get('NewWorkerConfigs/findOne').then(res => { + // return this.worker = Object.assign({}, res.data); + // }); // DELETE this.worker = { fi: '73226971P', @@ -74,6 +74,13 @@ export default class Controller extends Section { // Province auto complete set province(selection) { this._province = selection; + + if (!selection) return; + + const country = selection.country; + + if (!this.worker.countryFk) + this.worker.countryFk = country.id; } get town() { @@ -87,13 +94,17 @@ export default class Controller extends Section { if (!selection) return; const province = selection.province; + const country = province.country; const postcodes = selection.postcodes; - if (!this.client.provinceFk) - this.client.provinceFk = province.id; + if (!this.worker.provinceFk) + this.worker.provinceFk = province.id; + + if (!this.worker.countryFk) + this.worker.countryFk = country.id; if (postcodes.length === 1) - this.client.postcode = postcodes[0].code; + this.worker.postcode = postcodes[0].code; } get postcode() { @@ -108,18 +119,22 @@ export default class Controller extends Section { const town = selection.town; const province = town.province; + const country = province.country; - if (!this.client.city) - this.client.city = town.name; + if (!this.worker.city) + this.worker.city = town.name; - if (!this.client.provinceFk) - this.client.provinceFk = province.id; + if (!this.worker.provinceFk) + this.worker.provinceFk = province.id; + + if (!this.worker.countryFk) + this.worker.countryFk = country.id; } onResponse(response) { - this.client.postcode = response.code; - this.client.city = response.city; - this.client.provinceFk = response.provinceFk; + this.worker.postcode = response.code; + this.worker.city = response.city; + this.worker.provinceFk = response.provinceFk; } } From 9b9824939835b2fa6de8ca618c2e40e3590c07aa Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 4 Jan 2023 09:23:18 +0100 Subject: [PATCH 14/18] test: front test and e2e --- ...aclProfileType.sql => 00-createWorker.sql} | 2 +- e2e/helpers/selectors.js | 1 + e2e/helpers/tests.js | 26 +++++----- e2e/paths/03-worker/06_create.spec.js | 23 ++++++--- modules/worker/front/create/index.js | 26 ++-------- modules/worker/front/create/index.spec.js | 49 +++++++++++-------- 6 files changed, 62 insertions(+), 65 deletions(-) rename db/changes/230201/{00-aclProfileType.sql => 00-createWorker.sql} (96%) diff --git a/db/changes/230201/00-aclProfileType.sql b/db/changes/230201/00-createWorker.sql similarity index 96% rename from db/changes/230201/00-aclProfileType.sql rename to db/changes/230201/00-createWorker.sql index cae7166c9..d4118b4fa 100644 --- a/db/changes/230201/00-aclProfileType.sql +++ b/db/changes/230201/00-createWorker.sql @@ -31,7 +31,7 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `pri VALUES ('Worker', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'hr'), ('Worker', 'createAbsence', '*', 'ALLOW', 'ROLE', 'employee'), - ('Worker', 'updateAbsence', '*', 'ALLOW', 'ROLE', 'employee'), + ('Worker', 'updateAbsence', 'WRITE', 'ALLOW', 'ROLE', 'employee'), ('Worker', 'deleteAbsence', '*', 'ALLOW', 'ROLE', 'employee'), ('Worker', 'new', 'WRITE', 'ALLOW', 'ROLE', 'hr'), ('Role', '*', 'READ', 'ALLOW', 'ROLE', 'hr'); diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 134e41796..6bfb38e5d 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -58,6 +58,7 @@ export default { deleteAccount: '.vn-menu [name="deleteUser"]', setPassword: '.vn-menu [name="setPassword"]', activateAccount: '.vn-menu [name="enableAccount"]', + disableAccount: '.vn-menu [name="disableAccount"]', activateUser: '.vn-menu [name="activateUser"]', deactivateUser: '.vn-menu [name="deactivateUser"]', newPassword: 'vn-textfield[ng-model="$ctrl.newPassword"]', diff --git a/e2e/helpers/tests.js b/e2e/helpers/tests.js index 9ac616011..aac9963dd 100644 --- a/e2e/helpers/tests.js +++ b/e2e/helpers/tests.js @@ -25,20 +25,20 @@ async function test() { const jasmine = new Jasmine(); const specFiles = [ - // `./e2e/paths/01*/*[sS]pec.js`, - // `./e2e/paths/02*/*[sS]pec.js`, + `./e2e/paths/01*/*[sS]pec.js`, + `./e2e/paths/02*/*[sS]pec.js`, `./e2e/paths/03*/*[sS]pec.js`, - // `./e2e/paths/04*/*[sS]pec.js`, - // `./e2e/paths/05*/*[sS]pec.js`, - // `./e2e/paths/06*/*[sS]pec.js`, - // `./e2e/paths/07*/*[sS]pec.js`, - // `./e2e/paths/08*/*[sS]pec.js`, - // `./e2e/paths/09*/*[sS]pec.js`, - // `./e2e/paths/10*/*[sS]pec.js`, - // `./e2e/paths/11*/*[sS]pec.js`, - // `./e2e/paths/12*/*[sS]pec.js`, - // `./e2e/paths/13*/*[sS]pec.js`, - // `./e2e/paths/**/*[sS]pec.js` + `./e2e/paths/04*/*[sS]pec.js`, + `./e2e/paths/05*/*[sS]pec.js`, + `./e2e/paths/06*/*[sS]pec.js`, + `./e2e/paths/07*/*[sS]pec.js`, + `./e2e/paths/08*/*[sS]pec.js`, + `./e2e/paths/09*/*[sS]pec.js`, + `./e2e/paths/10*/*[sS]pec.js`, + `./e2e/paths/11*/*[sS]pec.js`, + `./e2e/paths/12*/*[sS]pec.js`, + `./e2e/paths/13*/*[sS]pec.js`, + `./e2e/paths/**/*[sS]pec.js` ]; jasmine.loadConfig({ diff --git a/e2e/paths/03-worker/06_create.spec.js b/e2e/paths/03-worker/06_create.spec.js index b93dace88..c1a555cbb 100644 --- a/e2e/paths/03-worker/06_create.spec.js +++ b/e2e/paths/03-worker/06_create.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -xdescribe('Worker calendar path', () => { +describe('Worker calendar path', () => { let browser; let page; let newWorker; @@ -58,15 +58,22 @@ xdescribe('Worker calendar path', () => { expect(message.text).toContain('Data saved!'); }); - xit('rollback', async() => { + it('rollback', async() => { await page.loginAndModule('sysadmin', 'account'); await page.accessToSearchResult(newWorker); - await page.accessToSection('account.card.summary'); - await page.waitToClick(selectors.accountDescriptor.menuButton); - await page.waitToClick(selectors.accountDescriptor.deleteAccount); - await page.waitToClick(selectors.accountDescriptor.acceptButton); - const message = await page.waitForSnackbar(); - expect(message.text).toContain('User removed'); + await page.waitToClick(selectors.accountDescriptor.menuButton); + await page.waitToClick(selectors.accountDescriptor.deactivateUser); + await page.waitToClick(selectors.accountDescriptor.acceptButton); + let message = await page.waitForSnackbar(); + + expect(message.text).toContain('User deactivated!'); + + await page.waitToClick(selectors.accountDescriptor.menuButton); + await page.waitToClick(selectors.accountDescriptor.disableAccount); + await page.waitToClick(selectors.accountDescriptor.acceptButton); + message = await page.waitForSnackbar(); + + expect(message.text).toContain('Account disabled!'); }); }); diff --git a/modules/worker/front/create/index.js b/modules/worker/front/create/index.js index 7965ab7e7..b80b3ae94 100644 --- a/modules/worker/front/create/index.js +++ b/modules/worker/front/create/index.js @@ -4,29 +4,9 @@ import Section from 'salix/components/section'; export default class Controller extends Section { constructor($element, $) { super($element, $); - // this.$http.get('NewWorkerConfigs/findOne').then(res => { - // return this.worker = Object.assign({}, res.data); - // }); - // DELETE - this.worker = { - fi: '73226971P', - name: 'ASDASD', - firstName: 'Test', - lastNames: 'Test', - email: 'developer4@mydomain.com', - roleFk: 1, - street: 'S/ ', - city: 'asd', - provinceFk: 1, - iban: 'ES2420386579855387888566', - bankEntityFk: 128, - companyFk: 442, - postcode: 'asd', - phone: '633342693', - code: 'ASD', - bossFk: 34, - birth: '2022-12-11T23:00:00.000Z' - }; + this.$http.get('NewWorkerConfigs/findOne').then(res => { + return this.worker = Object.assign({}, res.data); + }); } onSubmit() { diff --git a/modules/worker/front/create/index.spec.js b/modules/worker/front/create/index.spec.js index 24fc80d21..eac6c8bf0 100644 --- a/modules/worker/front/create/index.spec.js +++ b/modules/worker/front/create/index.spec.js @@ -1,12 +1,12 @@ import './index'; -describe('Client', () => { - describe('Component vnClientCreate', () => { +describe('Worker', () => { + describe('Component vnWorkerCreate', () => { let $scope; let $state; let controller; - beforeEach(ngModule('client')); + beforeEach(ngModule('worker')); beforeEach(inject(($componentController, $rootScope, _$state_) => { $scope = $rootScope.$new(); @@ -20,28 +20,23 @@ describe('Client', () => { }; } }; - const $element = angular.element(''); - controller = $componentController('vnClientCreate', {$element, $scope}); + const $element = angular.element(''); + controller = $componentController('vnWorkerCreate', {$element, $scope}); + controller.worker = {}; })); - it('should define and set scope, state and client properties', () => { - expect(controller.$).toBe($scope); - expect(controller.$state).toBe($state); - expect(controller.client.active).toBe(true); - }); - describe('onSubmit()', () => { it(`should call submit() on the watcher then expect a callback`, () => { jest.spyOn($state, 'go'); controller.onSubmit(); - expect(controller.$state.go).toHaveBeenCalledWith('client.card.basicData', {id: '1234'}); + expect(controller.$state.go).toHaveBeenCalledWith('worker.card.basicData', {id: '1234'}); }); }); describe('province() setter', () => { it(`should set countryFk property`, () => { - controller.client.countryFk = null; + controller.worker.countryFk = null; controller.province = { id: 1, name: 'New york', @@ -51,7 +46,7 @@ describe('Client', () => { } }; - expect(controller.client.countryFk).toEqual(2); + expect(controller.worker.countryFk).toEqual(2); }); }); @@ -71,7 +66,7 @@ describe('Client', () => { postcodes: [] }; - expect(controller.client.provinceFk).toEqual(1); + expect(controller.worker.provinceFk).toEqual(1); }); it(`should set provinceFk property and fill the postalCode if there's just one`, () => { @@ -89,8 +84,8 @@ describe('Client', () => { postcodes: [{code: '46001'}] }; - expect(controller.client.provinceFk).toEqual(1); - expect(controller.client.postcode).toEqual('46001'); + expect(controller.worker.provinceFk).toEqual(1); + expect(controller.worker.postcode).toEqual('46001'); }); }); @@ -113,9 +108,23 @@ describe('Client', () => { } }; - expect(controller.client.city).toEqual('New York'); - expect(controller.client.provinceFk).toEqual(1); - expect(controller.client.countryFk).toEqual(2); + expect(controller.worker.city).toEqual('New York'); + expect(controller.worker.provinceFk).toEqual(1); + expect(controller.worker.countryFk).toEqual(2); + }); + }); + + describe('generateCodeUser()', () => { + it(`should generate worker code and name `, () => { + controller.worker = { + firstName: 'default', + lastNames: 'generate worker' + }; + + controller.generateCodeUser(); + + expect(controller.worker.code).toEqual('DGW'); + expect(controller.worker.name).toEqual('defaultgw'); }); }); }); From 9c044dc95b71cc1d2da391a4a28209485d74d7f3 Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 4 Jan 2023 09:38:43 +0100 Subject: [PATCH 15/18] fix: phone --- modules/worker/back/methods/worker/specs/new.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/worker/back/methods/worker/specs/new.spec.js b/modules/worker/back/methods/worker/specs/new.spec.js index 2cb8bebef..d6b226ad2 100644 --- a/modules/worker/back/methods/worker/specs/new.spec.js +++ b/modules/worker/back/methods/worker/specs/new.spec.js @@ -32,7 +32,7 @@ describe('Worker new', () => { bankEntityFk: 128, companyFk: 442, postcode: '46680', - phone: '633342693', + phone: '123456789', code: 'DWW', bossFk: 9, birth: '2022-12-11T23:00:00.000Z' From ecfad940571fef9ecfb2c855dc8a63369d4acbe7 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 16 Jan 2023 12:19:03 +0100 Subject: [PATCH 16/18] refactor(worker_new): remove roleFk and profileType --- db/changes/230201/00-createWorker.sql | 29 +++----------- db/dump/fixtures.sql | 4 ++ e2e/paths/03-worker/06_create.spec.js | 23 +++++------ modules/worker/back/methods/worker/new.js | 26 +++++-------- .../back/methods/worker/specs/new.spec.js | 1 - modules/worker/back/model-config.json | 34 ++++++++-------- ...-worker-config.json => worker-config.json} | 16 +------- modules/worker/front/create/index.html | 39 ++++++------------- modules/worker/front/create/index.js | 7 ++-- modules/worker/front/create/index.spec.js | 4 +- 10 files changed, 65 insertions(+), 118 deletions(-) rename modules/worker/back/models/{new-worker-config.json => worker-config.json} (58%) diff --git a/db/changes/230201/00-createWorker.sql b/db/changes/230201/00-createWorker.sql index d4118b4fa..7ca2c41ee 100644 --- a/db/changes/230201/00-createWorker.sql +++ b/db/changes/230201/00-createWorker.sql @@ -1,22 +1,3 @@ - -INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) - VALUES - ('ProfileType', '*', '*', 'ALLOW', 'ROLE', 'employee'); - -CREATE TABLE `vn`.`newWorkerConfig` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `street` VARCHAR(25) NULL, - `provinceFk` smallint(6) unsigned NULL, - `companyFk` smallint(5) unsigned NULL, - `profileTypeFk` INT(11) NULL, - `roleFk` int(10) unsigned NULL, - PRIMARY KEY (`id`), - CONSTRAINT `newWorkerConfig_province_fk` FOREIGN KEY (`provinceFk`) REFERENCES `vn`.`province` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `newWorkerConfig_company_fk` FOREIGN KEY (`companyFk`) REFERENCES `vn`.`company` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `newWorkerConfig_profileType_fk` FOREIGN KEY (`profileTypeFk`) REFERENCES `vn`.`profileType` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `newWorkerConfig_role_fk` FOREIGN KEY (`roleFk`) REFERENCES `account`.`role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -); - UPDATE `salix`.`ACL` SET accessType='READ' WHERE model='Worker' @@ -36,8 +17,8 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `pri ('Worker', 'new', 'WRITE', 'ALLOW', 'ROLE', 'hr'), ('Role', '*', 'READ', 'ALLOW', 'ROLE', 'hr'); -/* -INSERT INTO `vn`.`newWorkerConfig` (`id`, `street`, `provinceFk`, `companyFk`, `profileTypeFk`, `roleFk`) - VALUES - (1, 'C/ ', 57, 442, 1, 1); -*/ +ALTER TABLE `vn`.`workerConfig` ADD roleFk int(10) unsigned NOT NULL COMMENT 'Rol por defecto al dar de alta un trabajador nuevo'; +UPDATE `vn`.`workerConfig` + SET roleFk = 1 + WHERE id = 1; + diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index eae831aea..3fc40f75f 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2769,3 +2769,7 @@ INSERT INTO `vn`.`payDemDetail` (`id`, `detail`) VALUES (1, 1); +INSERT INTO `vn`.`workerConfig` (`id`, `businessUpdated`, `roleFk`) + VALUES + (1, NULL, 1); + diff --git a/e2e/paths/03-worker/06_create.spec.js b/e2e/paths/03-worker/06_create.spec.js index c1a555cbb..5f6f5cf9f 100644 --- a/e2e/paths/03-worker/06_create.spec.js +++ b/e2e/paths/03-worker/06_create.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -describe('Worker calendar path', () => { +describe('Worker create path', () => { let browser; let page; let newWorker; @@ -23,13 +23,12 @@ describe('Worker calendar path', () => { await page.write(selectors.workerCreate.fi, '78457139E'); await page.write(selectors.workerCreate.phone, '12356789'); await page.write(selectors.workerCreate.postcode, '46680'); - await page.write(selectors.workerCreate.street, 'Doomstadt'); + await page.write(selectors.workerCreate.street, 'S/ Doomstadt'); await page.write(selectors.workerCreate.email, 'doctorDoom@marvel.com'); await page.write(selectors.workerCreate.iban, 'ES9121000418450200051332'); await page.autocompleteSearch(selectors.workerCreate.switft, 'BBKKESMMMMM'); - }); - it('should check for autocompleted worker code and worker user name', async() => { + // should check for autocompleted worker code and worker user name const workerCode = await page .waitToGetProperty(selectors.workerCreate.code, 'value'); @@ -38,34 +37,30 @@ describe('Worker calendar path', () => { expect(workerCode).toEqual('VVD'); expect(newWorker).toContain('victorvd'); - }); - it('should fail if necessary data is void', async() => { + // should fail if necessary data is void await page.waitToClick(selectors.workerCreate.createButton); - const message = await page.waitForSnackbar(); + let message = await page.waitForSnackbar(); expect(message.text).toContain('is a required argument'); - }); - it('should create a new worker and go to worker basic data', async() => { + // should create a new worker and go to worker basic data' await page.pickDate(selectors.workerCreate.birth, new Date(1962, 8, 5)); - await page.autocompleteSearch(selectors.workerCreate.role, 'Jefe de personal de reparto'); await page.autocompleteSearch(selectors.workerCreate.boss, 'deliveryBoss'); await page.waitToClick(selectors.workerCreate.createButton); - const message = await page.waitForSnackbar(); + message = await page.waitForSnackbar(); await page.waitForState('worker.card.basicData'); expect(message.text).toContain('Data saved!'); - }); - it('rollback', async() => { + // 'rollback' await page.loginAndModule('sysadmin', 'account'); await page.accessToSearchResult(newWorker); await page.waitToClick(selectors.accountDescriptor.menuButton); await page.waitToClick(selectors.accountDescriptor.deactivateUser); await page.waitToClick(selectors.accountDescriptor.acceptButton); - let message = await page.waitForSnackbar(); + message = await page.waitForSnackbar(); expect(message.text).toContain('User deactivated!'); diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js index b6da3301a..a7bb883cd 100644 --- a/modules/worker/back/methods/worker/new.js +++ b/modules/worker/back/methods/worker/new.js @@ -1,8 +1,9 @@ +/* eslint max-len: ["error", { "code": 130 }]*/ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('new', { - description: 'Creates a new ticket and returns the id', + description: 'Creates a new worker and returns the id', accessType: 'WRITE', accepts: [ { @@ -35,12 +36,6 @@ module.exports = Self => { description: `The worker email`, required: true, }, - { - arg: 'roleFk', - type: 'number', - description: `The worker role`, - required: true, - }, { arg: 'street', type: 'string', @@ -106,12 +101,6 @@ module.exports = Self => { type: 'date', description: `The worker birth`, required: true, - }, - { - arg: 'profileTypeFk', - type: 'number', - description: `The worker profile type ¿DELETE?`, - required: true, } ], returns: { @@ -150,6 +139,7 @@ module.exports = Self => { if (!client) { const nickname = args.firstName.concat(' ', args.lastNames); + const workerConfig = await models.WorkerConfig.findOne({fields: ['roleFk']}); const [randomPassword] = await models.Worker.rawSql( 'SELECT account.passwordGenerate() as password;' ); @@ -160,7 +150,7 @@ module.exports = Self => { nickname, password: randomPassword.password, email: args.email, - role: args.roleFk, + roleFk: workerConfig.roleFk, }, myOptions ); @@ -198,13 +188,17 @@ module.exports = Self => { provinceFk: args.provinceFk, postalCode: args.postalCode, mobile: args.phone, - nickname: 'TR ' + nickname, + nickname: nickname, isDefaultAddress: true, }, myOptions ); - client = await models.Client.findById(user.id, null, myOptions); + client = await models.Client.findById( + user.id, + {fields: ['id', 'name', 'socialName', 'street', 'city', 'iban', 'bankEntityFk', 'defaultAddressFk']}, + myOptions + ); await client.updateAttributes( { diff --git a/modules/worker/back/methods/worker/specs/new.spec.js b/modules/worker/back/methods/worker/specs/new.spec.js index d6b226ad2..f695ab80e 100644 --- a/modules/worker/back/methods/worker/specs/new.spec.js +++ b/modules/worker/back/methods/worker/specs/new.spec.js @@ -24,7 +24,6 @@ describe('Worker new', () => { firstName: 'default', lastNames: 'worker', email: 'defaultWorker@mydomain.com', - roleFk: 1, street: 'S/ defaultWorkerStreet', city: 'defaultWorkerCity', provinceFk: 1, diff --git a/modules/worker/back/model-config.json b/modules/worker/back/model-config.json index de8aadd41..7e03c8a23 100644 --- a/modules/worker/back/model-config.json +++ b/modules/worker/back/model-config.json @@ -26,9 +26,6 @@ "Journey": { "dataSource": "vn" }, - "NewWorkerConfig":{ - "dataSource": "vn" - }, "ProfileType":{ "dataSource": "vn" }, @@ -41,36 +38,42 @@ "WorkCenterHoliday": { "dataSource": "vn" }, - "WorkerDms": { + "Worker": { "dataSource": "vn" }, - "Worker": { + "WorkerConfig": { + "dataSource": "vn" + }, + "WorkerDepartment": { + "dataSource": "vn" + }, + "WorkerDisableExcluded": { + "dataSource": "vn" + }, + "WorkerDms": { "dataSource": "vn" }, "WorkerLabour": { "dataSource": "vn" }, + "WorkerLog": { + "dataSource": "vn" + }, "WorkerMana": { "dataSource": "vn" }, + "WorkerMedia": { + "dataSource": "vn" + }, "WorkerTeam": { "dataSource": "vn" }, "WorkerTeamCollegues": { "dataSource": "vn" }, - "WorkerMedia": { - "dataSource": "vn" - }, - "WorkerDepartment": { - "dataSource": "vn" - }, "WorkerTimeControl": { "dataSource": "vn" }, - "WorkerLog": { - "dataSource": "vn" - }, "WorkerTimeControlConfig": { "dataSource": "vn" }, @@ -79,9 +82,6 @@ }, "WorkerTimeControlMail": { "dataSource": "vn" - }, - "WorkerDisableExcluded": { - "dataSource": "vn" } } diff --git a/modules/worker/back/models/new-worker-config.json b/modules/worker/back/models/worker-config.json similarity index 58% rename from modules/worker/back/models/new-worker-config.json rename to modules/worker/back/models/worker-config.json index 2102d236c..05cdfef42 100644 --- a/modules/worker/back/models/new-worker-config.json +++ b/modules/worker/back/models/worker-config.json @@ -1,9 +1,9 @@ { - "name": "NewWorkerConfig", + "name": "WorkerConfig", "base": "VnModel", "options": { "mysql": { - "table": "newWorkerConfig" + "table": "workerConfig" } }, "properties": { @@ -12,18 +12,6 @@ "id": true, "description": "Identifier" }, - "street": { - "type": "string" - }, - "provinceFk": { - "type": "number" - }, - "companyFk": { - "type": "number" - }, - "profileTypeFk": { - "type": "number" - }, "roleFk": { "type": "number" } diff --git a/modules/worker/front/create/index.html b/modules/worker/front/create/index.html index c09930b80..5f5ab9d07 100644 --- a/modules/worker/front/create/index.html +++ b/modules/worker/front/create/index.html @@ -52,19 +52,9 @@ - - {{name}} ({{country.country}}) - + + {{name}} ({{country.country}}) + - - - - { - return this.worker = Object.assign({}, res.data); - }); + this.worker = {companyFk: this.vnConfig.user.companyFk}; } onSubmit() { @@ -45,6 +43,9 @@ export default class Controller extends Section { this.worker.code = newCode.toUpperCase().slice(0, 3); this.worker.name = totalNameArray[0] + newCode.slice(1); + + if (!this.worker.companyFk) + this.worker.companyFk = this.vnConfig.user.companyFk; } get province() { diff --git a/modules/worker/front/create/index.spec.js b/modules/worker/front/create/index.spec.js index eac6c8bf0..c2e9acce0 100644 --- a/modules/worker/front/create/index.spec.js +++ b/modules/worker/front/create/index.spec.js @@ -23,6 +23,7 @@ describe('Worker', () => { const $element = angular.element(''); controller = $componentController('vnWorkerCreate', {$element, $scope}); controller.worker = {}; + controller.vnConfig = {user: {companyFk: 1}}; })); describe('onSubmit()', () => { @@ -115,7 +116,7 @@ describe('Worker', () => { }); describe('generateCodeUser()', () => { - it(`should generate worker code and name `, () => { + it(`should generate worker code, name and company `, () => { controller.worker = { firstName: 'default', lastNames: 'generate worker' @@ -125,6 +126,7 @@ describe('Worker', () => { expect(controller.worker.code).toEqual('DGW'); expect(controller.worker.name).toEqual('defaultgw'); + expect(controller.worker.companyFk).toEqual(controller.vnConfig.user.companyFk); }); }); }); From ace7a5939ece2caeb159351e86f3bd966fa4e0c6 Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 20 Jan 2023 08:33:59 +0100 Subject: [PATCH 17/18] move to changes 230401 --- db/changes/230401/.gitkeep | 0 db/changes/{230201 => 230401}/00-createWorker.sql | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 db/changes/230401/.gitkeep rename db/changes/{230201 => 230401}/00-createWorker.sql (100%) diff --git a/db/changes/230401/.gitkeep b/db/changes/230401/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/db/changes/230201/00-createWorker.sql b/db/changes/230401/00-createWorker.sql similarity index 100% rename from db/changes/230201/00-createWorker.sql rename to db/changes/230401/00-createWorker.sql From 30885a499ee19016ec87dc55609fc2a83b35d608 Mon Sep 17 00:00:00 2001 From: jgallego Date: Sat, 21 Jan 2023 07:29:27 +0100 Subject: [PATCH 18/18] link --- print/templates/email/printer-setup/locale/es.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/print/templates/email/printer-setup/locale/es.yml b/print/templates/email/printer-setup/locale/es.yml index 77a3a7299..7361e5ed3 100644 --- a/print/templates/email/printer-setup/locale/es.yml +++ b/print/templates/email/printer-setup/locale/es.yml @@ -8,8 +8,8 @@ description: https://www.youtube.com/watch?v=qhb0kgQF3o8. También necesitarás el QLabel, el programa para imprimir las cintas. - downloadFrom: Puedes descargarlo desde este enlace https://godex.s3-accelerate.amazonaws.com/gGnOPoojkP6vC1lgmrbEqQ.file?v01 + downloadFrom: Puedes descargarlo desde este enlace https://cdn.verdnatura.es/public/QLabel_IV_V1.37_Install_en.exe downloadDriver: En este enlace puedes descargar el driver de la impresora https://es.seagullscientific.com/support/downloads/drivers/godex/download/ sections: