diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8a04cfe8..41374b4df 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,25 +8,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [2304.01] - 2023-02-09
### Added
--
+- (Trabajadores -> Nuevo trabajador) Nueva sección
### Changed
--
+-
### Fixed
--
+-
## [2302.01] - 2023-01-26
### Added
-- (General -> Inicio) Permite recuperar la contraseña
-- (Tickets -> Opciones) Subir albarán a Docuware
-- (Tickets -> Opciones) Enviar correo con PDF de Docuware
-- (Artículos -> Datos Básicos) Añadido campo Unidades/Caja
+- (General -> Inicio) Permite recuperar la contraseña
+- (Tickets -> Opciones) Subir albarán a Docuware
+- (Tickets -> Opciones) Enviar correo con PDF de Docuware
+- (Artículos -> Datos Básicos) Añadido campo Unidades/Caja
### Changed
-- (Reclamaciones -> Descriptor) Cambiado el campo Agencia por Zona
-- (Tickets -> Líneas preparadas) Actualizada sección para que sea más visual
+- (Reclamaciones -> Descriptor) Cambiado el campo Agencia por Zona
+- (Tickets -> Líneas preparadas) Actualizada sección para que sea más visual
### Fixed
- (General) Al utilizar el traductor de Google se descuadraban los iconos
diff --git a/db/changes/230401/.gitkeep b/db/changes/230401/.gitkeep
deleted file mode 100644
index e69de29bb..000000000
diff --git a/db/changes/230401/00-createWorker.sql b/db/changes/230401/00-createWorker.sql
new file mode 100644
index 000000000..7ca2c41ee
--- /dev/null
+++ b/db/changes/230401/00-createWorker.sql
@@ -0,0 +1,24 @@
+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', 'WRITE', 'ALLOW', 'ROLE', 'employee'),
+ ('Worker', 'deleteAbsence', '*', 'ALLOW', 'ROLE', 'employee'),
+ ('Worker', 'new', 'WRITE', 'ALLOW', 'ROLE', 'hr'),
+ ('Role', '*', 'READ', 'ALLOW', 'ROLE', 'hr');
+
+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 27e72708f..218fcb9ca 100644
--- a/db/dump/fixtures.sql
+++ b/db/dump/fixtures.sql
@@ -2629,7 +2629,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`)
@@ -2751,10 +2751,14 @@ INSERT INTO `vn`.`mdbApp` (`app`, `baselineBranchFk`, `userFk`, `locked`)
VALUES
('foo', 'master', NULL, NULL),
('bar', 'test', 9, util.VN_NOW());
-INSERT INTO `vn`.`ticketLog` (`id`, `originFk`, `userFk`, `action`, `changedModel`, `oldInstance`, `newInstance`, `changedModelId`)
- VALUES
- (1, 1, 9, 'insert', 'Ticket', '{}', '{"clientFk":1, "nickname": "Bat cave"}', 1);
+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
@@ -2765,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/helpers/selectors.js b/e2e/helpers/selectors.js
index e9d9d0580..a1412f431 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"]',
@@ -969,6 +970,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',
@@ -1021,6 +1023,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/paths/03-worker/06_create.spec.js b/e2e/paths/03-worker/06_create.spec.js
new file mode 100644
index 000000000..5f6f5cf9f
--- /dev/null
+++ b/e2e/paths/03-worker/06_create.spec.js
@@ -0,0 +1,74 @@
+import selectors from '../../helpers/selectors.js';
+import getBrowser from '../../helpers/puppeteer';
+
+describe('Worker create 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, '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');
+
+ // should check for autocompleted worker code and worker user name
+ 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');
+
+ // should fail if necessary data is void
+ await page.waitToClick(selectors.workerCreate.createButton);
+ let message = await page.waitForSnackbar();
+
+ expect(message.text).toContain('is a required argument');
+
+ // 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.boss, 'deliveryBoss');
+ await page.waitToClick(selectors.workerCreate.createButton);
+ message = await page.waitForSnackbar();
+ await page.waitForState('worker.card.basicData');
+
+ expect(message.text).toContain('Data saved!');
+
+ // '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);
+ 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/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/loopback/locale/es.json b/loopback/locale/es.json
index f6f305dc3..d65054f37 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -252,9 +252,12 @@
"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",
"App name does not exist": "El nombre de aplicación no es válido",
"Try again": "Vuelve a intentarlo",
"Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9",
"Failed to upload file": "Error al subir archivo",
"The DOCUWARE PDF document does not exists": "The DOCUWARE PDF document does not exists"
-}
\ No newline at end of file
+}
diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js
new file mode 100644
index 000000000..a7bb883cd
--- /dev/null
+++ b/modules/worker/back/methods/worker/new.js
@@ -0,0 +1,256 @@
+/* eslint max-len: ["error", { "code": 130 }]*/
+const UserError = require('vn-loopback/util/user-error');
+
+module.exports = Self => {
+ Self.remoteMethodCtx('new', {
+ description: 'Creates a new worker and returns the id',
+ accessType: 'WRITE',
+ accepts: [
+ {
+ arg: 'fi',
+ type: 'string',
+ description: `The worker fi`,
+ required: true,
+ },
+ {
+ arg: 'name',
+ type: 'string',
+ description: `The user name`,
+ required: true,
+ },
+ {
+ arg: 'firstName',
+ type: 'string',
+ description: `The worker firstname`,
+ required: true,
+ },
+ {
+ arg: 'lastNames',
+ type: 'string',
+ description: `The worker lastnames`,
+ required: true,
+ },
+ {
+ arg: 'email',
+ type: 'string',
+ description: `The worker email`,
+ required: true,
+ },
+ {
+ arg: 'street',
+ type: 'string',
+ description: `The worker address`,
+ required: true,
+ },
+ {
+ arg: 'city',
+ type: 'string',
+ description: `The worker city`,
+ required: true,
+ },
+ {
+ arg: 'provinceFk',
+ type: 'number',
+ description: `The worker province`,
+ required: true,
+ },
+ {
+ arg: 'iban',
+ type: 'string',
+ description: `The worker iban`,
+ required: true,
+ },
+ {
+ arg: 'bankEntityFk',
+ type: 'number',
+ description: `The worker bank entity`,
+ required: true,
+ },
+ {
+ arg: 'companyFk',
+ type: 'number',
+ description: `The worker company`,
+ required: true,
+ },
+ {
+ arg: 'postcode',
+ type: 'string',
+ description: `The worker postcode`,
+ required: true,
+ },
+ {
+ arg: 'phone',
+ type: 'string',
+ description: `The worker phone`,
+ required: true,
+ },
+ {
+ arg: 'code',
+ type: 'string',
+ description: `The worker code`,
+ required: true,
+ },
+ {
+ arg: 'bossFk',
+ type: 'number',
+ description: `The worker boss`,
+ required: true,
+ },
+ {
+ arg: 'birth',
+ type: 'date',
+ description: `The worker birth`,
+ required: true,
+ }
+ ],
+ 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: args.fi},
+ },
+ myOptions
+ );
+
+ 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;'
+ );
+
+ const user = await models.Account.create(
+ {
+ name: args.name,
+ nickname,
+ password: randomPassword.password,
+ email: args.email,
+ roleFk: workerConfig.roleFk,
+ },
+ myOptions
+ );
+
+ await models.UserAccount.create(
+ {
+ id: user.id,
+ },
+ myOptions
+ );
+
+ await models.Worker.rawSql(
+ 'CALL vn.clientCreate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
+ [
+ args.firstName,
+ args.lastNames,
+ args.fi,
+ args.street,
+ args.postalCode,
+ args.city,
+ args.provinceFk,
+ args.companyFk,
+ args.phone,
+ args.email,
+ 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: nickname,
+ isDefaultAddress: true,
+ },
+ myOptions
+ );
+
+ client = await models.Client.findById(
+ user.id,
+ {fields: ['id', 'name', 'socialName', 'street', 'city', 'iban', 'bankEntityFk', 'defaultAddressFk']},
+ myOptions
+ );
+
+ await client.updateAttributes(
+ {
+ iban: args.iban,
+ bankEntityFk: args.bankEntityFk,
+ defaultAddressFk: address.id,
+ },
+ 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(?, ?, ?, ?, ?, ?, ?)',
+ [
+ args.firstName,
+ args.lastNames,
+ args.code,
+ args.bossFk,
+ client.id,
+ args.fi,
+ args.birth,
+ ],
+ myOptions
+ );
+
+ if (tx) await tx.commit();
+ } catch (error) {
+ if (tx) await tx.rollback();
+ 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`);
+
+ 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 error;
+ }
+
+ await models.user.resetPassword({
+ email: args.email,
+ emailTemplate: 'worker-welcome',
+ id: client.id
+ });
+
+ return {id: client.id};
+ };
+};
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..f695ab80e
--- /dev/null
+++ b/modules/worker/back/methods/worker/specs/new.spec.js
@@ -0,0 +1,139 @@
+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',
+ street: 'S/ defaultWorkerStreet',
+ city: 'defaultWorkerCity',
+ provinceFk: 1,
+ iban: 'ES8304879798578129532677',
+ bankEntityFk: 128,
+ companyFk: 442,
+ postcode: '46680',
+ phone: '123456789',
+ 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/back/model-config.json b/modules/worker/back/model-config.json
index 3f3416504..7e03c8a23 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,19 @@
},
"Department": {
"dataSource": "vn"
- },
+ },
+ "Device": {
+ "dataSource": "vn"
+ },
"EducationLevel": {
"dataSource": "vn"
},
"Journey": {
"dataSource": "vn"
},
+ "ProfileType":{
+ "dataSource": "vn"
+ },
"Time": {
"dataSource": "vn"
},
@@ -32,39 +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"
},
- "Device": {
- "dataSource": "vn"
- },
- "WorkerLog": {
- "dataSource": "vn"
- },
"WorkerTimeControlConfig": {
"dataSource": "vn"
},
@@ -73,9 +82,6 @@
},
"WorkerTimeControlMail": {
"dataSource": "vn"
- },
- "WorkerDisableExcluded": {
- "dataSource": "vn"
}
}
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-config.json b/modules/worker/back/models/worker-config.json
new file mode 100644
index 000000000..05cdfef42
--- /dev/null
+++ b/modules/worker/back/models/worker-config.json
@@ -0,0 +1,27 @@
+{
+ "name": "WorkerConfig",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "workerConfig"
+ }
+ },
+ "properties": {
+ "id": {
+ "type": "number",
+ "id": true,
+ "description": "Identifier"
+ },
+ "roleFk": {
+ "type": "number"
+ }
+ },
+ "acls": [
+ {
+ "accessType": "READ",
+ "principalType": "ROLE",
+ "principalId": "$everyone",
+ "permission": "ALLOW"
+ }
+ ]
+}
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);
};
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..5f5ab9d07
--- /dev/null
+++ b/modules/worker/front/create/index.html
@@ -0,0 +1,194 @@
+
{{ $t('dearWorker') }},
+ +