diff --git a/db/changes/232801/00-client_create.sql b/db/changes/232801/00-client_create.sql new file mode 100644 index 000000000..0728ba05e --- /dev/null +++ b/db/changes/232801/00-client_create.sql @@ -0,0 +1,89 @@ +DROP PROCEDURE IF EXISTS vn.clientCreate; + +DELIMITER $$ +CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`client_create`( + vFirstname VARCHAR(50), + vSurnames VARCHAR(50), + vFi VARCHAR(9), + vAddress TEXT, + vPostcode CHAR(5), + vCity VARCHAR(25), + vProvinceFk SMALLINT(5), + vCompanyFk SMALLINT(5), + vPhone VARCHAR(11), + vEmail VARCHAR(255), + vUserFk INT +) +BEGIN +/** + * Create new client + * + * @params vFirstname firstName + * @params vSurnames surnames + * @params vFi company code from accounting transactions + * @params vAddress address + * @params vPostcode postCode + * @params vCity city + * @params vProvinceFk province + * @params vCompanyFk company in which he has become a client + * @params vPhone telephone number + * @params vEmail email address + * @params vUserFk user id + */ + DECLARE vPayMethodFk INT; + DECLARE vDueDay INT; + DECLARE vDefaultCredit DECIMAL(10, 2); + DECLARE vIsTaxDataChecked TINYINT(1); + DECLARE vHasCoreVnl BOOLEAN; + DECLARE vMandateTypeFk INT; + + SELECT defaultPayMethodFk, + defaultDueDay, + defaultCredit, + defaultIsTaxDataChecked, + defaultHasCoreVnl, + defaultMandateTypeFk + INTO vPayMethodFk, + vDueDay, + vDefaultCredit, + vIsTaxDataChecked, + vHasCoreVnl, + vMandateTypeFk + FROM clientConfig; + + INSERT INTO `client` + SET id = vUserFk, + name = CONCAT(vFirstname, ' ', vSurnames), + street = vAddress, + fi = TRIM(vFi), + phone = vPhone, + email = vEmail, + provinceFk = vProvinceFk, + city = vCity, + postcode = vPostcode, + socialName = CONCAT(vSurnames, ' ', vFirstname), + payMethodFk = vPayMethodFk, + dueDay = vDueDay, + credit = vDefaultCredit, + isTaxDataChecked = vIsTaxDataChecked, + hasCoreVnl = vHasCoreVnl, + isEqualizated = FALSE + ON duplicate KEY UPDATE + payMethodFk = vPayMethodFk, + dueDay = vDueDay, + credit = vDefaultCredit, + isTaxDataChecked = vIsTaxDataChecked, + hasCoreVnl = vHasCoreVnl, + isActive = TRUE; + + INSERT INTO mandate (clientFk, companyFk, mandateTypeFk) + SELECT vUserFk, vCompanyFk, vMandateTypeFk + WHERE NOT EXISTS ( + SELECT id + FROM mandate + WHERE clientFk = vUserFk + AND companyFk = vCompanyFk + AND mandateTypeFk = vMandateTypeFk + ); +END$$ +DELIMITER ; diff --git a/db/changes/232801/00-client_create2.sql b/db/changes/232801/00-client_create2.sql new file mode 100644 index 000000000..8ba4e78e5 --- /dev/null +++ b/db/changes/232801/00-client_create2.sql @@ -0,0 +1,17 @@ +ALTER TABLE vn.clientConfig ADD defaultPayMethodFk tinyint(3) unsigned NULL; +ALTER TABLE vn.clientConfig ADD defaultDueDay int unsigned NULL; +ALTER TABLE vn.clientConfig ADD defaultCredit decimal(10, 2) NULL; +ALTER TABLE vn.clientConfig ADD defaultIsTaxDataChecked tinyint(1) NULL; +ALTER TABLE vn.clientConfig ADD defaultHasCoreVnl boolean NULL; +ALTER TABLE vn.clientConfig ADD defaultMandateTypeFk smallint(5) NULL; +ALTER TABLE vn.clientConfig ADD CONSTRAINT clientNewConfigPayMethod_FK FOREIGN KEY (dafaultPayMethodFk) REFERENCES vn.payMethod(id); +ALTER TABLE vn.clientConfig ADD CONSTRAINT clientNewConfigMandateType_FK FOREIGN KEY (defaultMandateTypeFk) REFERENCES vn.mandateType(id); + +UPDATE vn.clientConfig + SET defaultPayMethodFk = 4, + defaultDueDay = 5, + defaultCredit = 300.0, + defaultIsTaxDataChecked = 1, + defaultHasCoreVnl = 1, + defaultMandateTypeFk = 2 + WHERE id = 1; \ No newline at end of file diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 46bccf9dc..14c9fba5d 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -385,9 +385,10 @@ INSERT INTO `vn`.`clientManaCache`(`clientFk`, `mana`, `dated`) (1103, 0, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)), (1104, -30, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)); -INSERT INTO `vn`.`clientConfig`(`riskTolerance`, `maxCreditRows`) +INSERT INTO `vn`.`clientConfig`(`id`, `riskTolerance`, `maxCreditRows`, `maxPriceIncreasingRatio`, `riskScope`, `defaultPayMethodFk`, `defaultDueDay`, `defaultCredit`, `defaultIsTaxDataChecked`, `defaultHasCoreVnl`, `defaultMandateTypeFk`) VALUES - (200, 10); + (1, 200, 10, 0.25, 2, 4, 5, 300.00, 1, 1, 2); + INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`) VALUES diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index d4a8a316f..b10813488 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -894,6 +894,18 @@ export default { extension: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(5) > section > span', }, + department: { + firstDepartment: 'vn-worker-department-index vn-card > vn-treeview vn-treeview-childs vn-treeview-childs vn-treeview-childs a' + }, + departmentSummary: { + header: 'vn-worker-department-summary h5', + name: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(1) > section > span', + code: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(2) > section > span', + chat: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(3) > section > span', + bossDepartment: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(4) > section > span', + email: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(5) > section > span', + clientFk: 'vn-worker-department-summary vn-horizontal > vn-one > vn-vertical > vn-label-value:nth-child(6) > section > span', + }, workerBasicData: { name: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.firstName"]', surname: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.lastName"]', @@ -901,6 +913,13 @@ export default { locker: 'vn-worker-basic-data vn-input-number[ng-model="$ctrl.worker.locker"]', saveButton: 'vn-worker-basic-data button[type=submit]' }, + departmentBasicData: { + Name: 'vn-worker-department-basic-data vn-textfield[ng-model="$ctrl.department.name"]', + Code: 'vn-worker-department-basic-data vn-textfield[ng-model="$ctrl.department.code"]', + Chat: 'vn-worker-department-basic-data vn-textfield[ng-model="$ctrl.department.chat"]', + Email: 'vn-worker-department-basic-data vn-textfield[ng-model="$ctrl.department.notificationEmail"]', + saveButton: 'vn-worker-department-basic-data button[type=submit]' + }, workerNotes: { addNoteFloatButton: 'vn-worker-note vn-icon[icon="add"]', note: 'vn-note-worker-create vn-textarea[ng-model="$ctrl.note.text"]', diff --git a/e2e/paths/03-worker/01-department/01_summary.spec.js b/e2e/paths/03-worker/01-department/01_summary.spec.js new file mode 100644 index 000000000..e4bf8fc2d --- /dev/null +++ b/e2e/paths/03-worker/01-department/01_summary.spec.js @@ -0,0 +1,29 @@ +import selectors from '../../../helpers/selectors.js'; +import getBrowser from '../../../helpers/puppeteer'; + +describe('department summary path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('hr', 'worker'); + await page.accessToSection('worker.department'); + await page.doSearch('INFORMATICA'); + await page.click(selectors.department.firstDepartment); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should reach the employee summary section and check all properties', async() => { + expect(await page.waitToGetProperty(selectors.departmentSummary.header, 'innerText')).toEqual('INFORMATICA'); + expect(await page.getProperty(selectors.departmentSummary.name, 'innerText')).toEqual('INFORMATICA'); + expect(await page.getProperty(selectors.departmentSummary.code, 'innerText')).toEqual('it'); + expect(await page.getProperty(selectors.departmentSummary.chat, 'innerText')).toEqual('informatica-cau'); + expect(await page.getProperty(selectors.departmentSummary.bossDepartment, 'innerText')).toEqual(''); + expect(await page.getProperty(selectors.departmentSummary.email, 'innerText')).toEqual('-'); + expect(await page.getProperty(selectors.departmentSummary.clientFk, 'innerText')).toEqual('-'); + }); +}); diff --git a/e2e/paths/03-worker/01-department/02-basicData.spec.js b/e2e/paths/03-worker/01-department/02-basicData.spec.js new file mode 100644 index 000000000..219d1426c --- /dev/null +++ b/e2e/paths/03-worker/01-department/02-basicData.spec.js @@ -0,0 +1,43 @@ +import getBrowser from '../../../helpers/puppeteer'; +import selectors from '../../../helpers/selectors.js'; + +const $ = { + form: 'vn-worker-department-basic-data form', +}; + +describe('department summary path', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('hr', 'worker'); + await page.accessToSection('worker.department'); + await page.doSearch('INFORMATICA'); + await page.click(selectors.department.firstDepartment); + }); + + beforeEach(async() => { + await page.accessToSection('worker.department.card.basicData'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it(`should edit the department basic data and confirm the department data was edited`, async() => { + const values = { + Name: 'Informatica', + Code: 'IT', + Chat: 'informatica-cau', + Email: 'it@verdnatura.es', + }; + + await page.fillForm($.form, values); + const formValues = await page.fetchForm($.form, Object.keys(values)); + const message = await page.sendForm($.form, values); + + expect(message.isSuccess).toBeTrue(); + expect(formValues).toEqual(values); + }); +}); diff --git a/loopback/locale/en.json b/loopback/locale/en.json index d6eec4f78..d33b3b3c3 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -147,14 +147,12 @@ "Receipt's bank was not found": "Receipt's bank was not found", "This receipt was not compensated": "This receipt was not compensated", "Client's email was not found": "Client's email was not found", - "Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}", + "Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº %d", "It is not possible to modify tracked sales": "It is not possible to modify tracked sales", "It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo", "It is not possible to modify cloned sales": "It is not possible to modify cloned sales", - "Valid priorities: 1,2,3": "Valid priorities: 1,2,3", "Warehouse inventory not set": "Almacén inventario no está establecido", "Component cost not set": "Componente coste no está estabecido", - "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2", "Description cannot be blank": "Description cannot be blank", "company": "Company", "country": "Country", @@ -178,5 +176,6 @@ "Failed to upload delivery note": "Error to upload delivery note {{id}}", "Mail not sent": "There has been an error sending the invoice to the client [{{clientId}}]({{{clientUrl}}}), please check the email address", "The renew period has not been exceeded": "The renew period has not been exceeded", - "You can not use the same password": "You can not use the same password" + "You can not use the same password": "You can not use the same password", + "Valid priorities": "Valid priorities: %d" } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 578a54c06..106df379e 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -268,7 +268,7 @@ "Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite", "Warehouse inventory not set": "El almacén inventario no está establecido", "This locker has already been assigned": "Esta taquilla ya ha sido asignada", - "Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº {{id}}", + "Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº %d", "Not exist this branch": "La rama no existe", "This ticket cannot be signed because it has not been boxed": "Este ticket no puede firmarse porque no ha sido encajado", "Collection does not exist": "La colección no existe", @@ -301,6 +301,7 @@ "Fecha fuera de rango": "Fecha fuera de rango", "Error while generating PDF": "Error al generar PDF", "Error when sending mail to client": "Error al enviar el correo al cliente", - "Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico", - "The renew period has not been exceeded": "El periodo de renovación no ha sido superado" + "Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico", + "The renew period has not been exceeded": "El periodo de renovación no ha sido superado", + "Valid priorities": "Prioridades válidas: %d" } diff --git a/modules/item/back/methods/item/new.js b/modules/item/back/methods/item/new.js index c82e2a6b1..b4b081cd7 100644 --- a/modules/item/back/methods/item/new.js +++ b/modules/item/back/methods/item/new.js @@ -1,4 +1,4 @@ -let UserError = require('vn-loopback/util/user-error'); +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('new', { @@ -49,7 +49,7 @@ module.exports = Self => { try { const itemConfig = await models.ItemConfig.findOne({fields: ['validPriorities']}, myOptions); if (!itemConfig.validPriorities.includes(params.priority)) - throw new UserError(`Valid priorities: ${[...itemConfig.validPriorities]}`); + throw new UserError('Valid priorities', 'VALID_PRIORITIES', [...itemConfig.validPriorities]); const provisionalName = params.provisionalName; delete params.provisionalName; diff --git a/modules/ticket/back/methods/ticket/setDeleted.js b/modules/ticket/back/methods/ticket/setDeleted.js index 4d7fe73d4..878cce056 100644 --- a/modules/ticket/back/methods/ticket/setDeleted.js +++ b/modules/ticket/back/methods/ticket/setDeleted.js @@ -50,7 +50,7 @@ module.exports = Self => { fields: ['id']} , myOptions); if (ticketRefunds.length > 0) - throw new UserError($t('Tickets with associated refunds', {id: ticketRefunds[0].id})); + throw new UserError('Tickets with associated refunds', 'TICKET_REFUND', ticketRefunds[0].id); // Check if has sales with shelving const canDeleteTicketWithPartPrepared = diff --git a/modules/worker/back/methods/department/getLeaves.js b/modules/worker/back/methods/department/getLeaves.js index b1ce2fbe8..38ff2ef3e 100644 --- a/modules/worker/back/methods/department/getLeaves.js +++ b/modules/worker/back/methods/department/getLeaves.js @@ -33,7 +33,6 @@ module.exports = Self => { map.set(node.parentFk, []); map.get(node.parentFk).push(node); } - function setLeaves(nodes) { if (!nodes) return; for (let node of nodes) { @@ -43,6 +42,7 @@ module.exports = Self => { } let leaves = map.get(parentId); + setLeaves(leaves); return leaves || []; diff --git a/modules/worker/back/methods/department/specs/getLeaves.spec.js b/modules/worker/back/methods/department/specs/getLeaves.spec.js new file mode 100644 index 000000000..fb7c84ff4 --- /dev/null +++ b/modules/worker/back/methods/department/specs/getLeaves.spec.js @@ -0,0 +1,10 @@ +const models = require('vn-loopback/server/server').models; + +describe('department getLeaves()', () => { + const ctx = {req: {accessToken: {userId: 9}}}; + it('should return the department and the childs containing the search value', async() => { + let result = await models.Department.getLeaves(ctx, null, 'INFORMATICA'); + + expect(result.length).toEqual(1); + }); +}); diff --git a/modules/worker/back/methods/worker/new.js b/modules/worker/back/methods/worker/new.js index 27acc98ab..199a3be62 100644 --- a/modules/worker/back/methods/worker/new.js +++ b/modules/worker/back/methods/worker/new.js @@ -171,7 +171,7 @@ module.exports = Self => { throw new UserError(`That payment method requires an IBAN`); await models.Worker.rawSql( - 'CALL vn.clientCreate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + 'CALL vn.client_create(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [ args.firstName, args.lastNames, diff --git a/modules/worker/back/models/department.json b/modules/worker/back/models/department.json index c3f627e93..edeba74f7 100644 --- a/modules/worker/back/models/department.json +++ b/modules/worker/back/models/department.json @@ -8,8 +8,9 @@ }, "properties": { "id": { + "type": "number", "id": true, - "type": "number" + "description": "Identifier" }, "code": { "type": "string" @@ -37,6 +38,30 @@ }, "hasToMistake": { "type": "number" + }, + "isTeleworking": { + "type": "boolean" + }, + "hasToRefill": { + "type": "boolean" + }, + "hasToSendMail": { + "type": "boolean" + }, + "isProduction": { + "type": "boolean" + } + }, + "relations": { + "client": { + "type": "belongsTo", + "model": "Client", + "foreignKey": "clientFk" + }, + "worker": { + "type": "belongsTo", + "model": "Worker", + "foreignKey": "workerFk" } } } diff --git a/modules/worker/back/models/worker.json b/modules/worker/back/models/worker.json index 88200a4a9..978d613e9 100644 --- a/modules/worker/back/models/worker.json +++ b/modules/worker/back/models/worker.json @@ -60,7 +60,7 @@ "user": { "type": "belongsTo", "model": "VnUser", - "foreignKey": "userFk" + "foreignKey": "id" }, "boss": { "type": "belongsTo", diff --git a/modules/worker/front/department/basic-data/index.html b/modules/worker/front/department/basic-data/index.html new file mode 100644 index 000000000..2d1e315d4 --- /dev/null +++ b/modules/worker/front/department/basic-data/index.html @@ -0,0 +1,102 @@ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/modules/worker/front/department/basic-data/index.js b/modules/worker/front/department/basic-data/index.js new file mode 100644 index 000000000..e2df4804a --- /dev/null +++ b/modules/worker/front/department/basic-data/index.js @@ -0,0 +1,10 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +ngModule.vnComponent('vnWorkerDepartmentBasicData', { + template: require('./index.html'), + controller: Section, + bindings: { + department: '<' + } +}); diff --git a/modules/worker/front/department/basic-data/locale/es.yml b/modules/worker/front/department/basic-data/locale/es.yml new file mode 100644 index 000000000..e9c5574dd --- /dev/null +++ b/modules/worker/front/department/basic-data/locale/es.yml @@ -0,0 +1,13 @@ +Name: Nombre +Code: Código +Chat: Chat +Email: Email +Boss department: Jefe del departamento +Self-consumption customer: Cliente autoconsumo +Telecommutes: Teletrabaja +Notify on errors: Notificar errores +worksInProduction: Pertenece a producción +Fill in days without physical check-ins: Completar días sin registros físicos +Send check-ins by email: Enviar fichadas por email +Save: Guardar +Undo changes: Deshacer cambios diff --git a/modules/worker/front/department/card/index.html b/modules/worker/front/department/card/index.html new file mode 100644 index 000000000..b9ae1a87b --- /dev/null +++ b/modules/worker/front/department/card/index.html @@ -0,0 +1,5 @@ + + + + + diff --git a/modules/worker/front/department/card/index.js b/modules/worker/front/department/card/index.js new file mode 100644 index 000000000..0a6e3e71c --- /dev/null +++ b/modules/worker/front/department/card/index.js @@ -0,0 +1,39 @@ +import ngModule from '../../module'; +import ModuleCard from 'salix/components/module-card'; + +class Controller extends ModuleCard { + reload() { + const filter = { + fields: ['id', 'name', 'code', 'workerFk', 'isProduction', 'chatName', + 'isTeleworking', 'notificationEmail', 'hasToRefill', 'hasToSendMail', 'hasToMistake', 'clientFk'], + include: [ + { + relation: 'client', + scope: { + fields: ['id', 'name'] + } + }, { + relation: 'worker', + scope: { + fields: ['id', 'firstName', 'lastName'], + include: { + relation: 'user', + scope: { + fields: ['name'] + } + } + } + } + ] + + }; + + this.$http.get(`Departments/${this.$params.id}`, {filter}) + .then(res => this.department = res.data); + } +} + +ngModule.vnComponent('vnWorkerDepartmentCard', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/worker/front/department/descriptor-popover/index.html b/modules/worker/front/department/descriptor-popover/index.html new file mode 100644 index 000000000..da305b1a2 --- /dev/null +++ b/modules/worker/front/department/descriptor-popover/index.html @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/modules/worker/front/department/descriptor-popover/index.js b/modules/worker/front/department/descriptor-popover/index.js new file mode 100644 index 000000000..dfbc2c1fc --- /dev/null +++ b/modules/worker/front/department/descriptor-popover/index.js @@ -0,0 +1,9 @@ +import ngModule from '../../module'; +import DescriptorPopover from 'salix/components/descriptor-popover'; + +class Controller extends DescriptorPopover {} + +ngModule.vnComponent('vnWorkerDepartmentDescriptorPopover', { + slotTemplate: require('./index.html'), + controller: Controller +}); diff --git a/modules/worker/front/department/descriptor/index.html b/modules/worker/front/department/descriptor/index.html new file mode 100644 index 000000000..d9f62353d --- /dev/null +++ b/modules/worker/front/department/descriptor/index.html @@ -0,0 +1,49 @@ + + + + Delete + + + +
+ + + + + + + + +
+ +
+
+ + + + + diff --git a/modules/worker/front/department/descriptor/index.js b/modules/worker/front/department/descriptor/index.js new file mode 100644 index 000000000..5ab1059d9 --- /dev/null +++ b/modules/worker/front/department/descriptor/index.js @@ -0,0 +1,45 @@ +import ngModule from '../../module'; +import Descriptor from 'salix/components/descriptor'; + +class Controller extends Descriptor { + constructor($element, $, $rootScope) { + super($element, $); + this.$rootScope = $rootScope; + } + + get department() { + return this.entity; + } + + set department(value) { + this.entity = value; + } + + filterDepartments(department, event) { + if (event.defaultPrevented) return; + event.preventDefault(); + event.stopPropagation(); + + this.$state.go(`worker.index`, + {q: JSON.stringify({departmentFk: department.id})}); + } + + deleteDepartment() { + return this.$http.delete(`Departments/${this.id}`) + .then(() => { + this.$state.go('worker.department'); + + this.vnApp.showSuccess(this.$t('Department deleted.')); + }); + } +} + +Controller.$inject = ['$element', '$scope', '$rootScope']; + +ngModule.vnComponent('vnWorkerDepartmentDescriptor', { + template: require('./index.html'), + controller: Controller, + bindings: { + department: '<' + } +}); diff --git a/modules/worker/front/department/index.js b/modules/worker/front/department/index.js index 15904a963..2d84ea79f 100644 --- a/modules/worker/front/department/index.js +++ b/modules/worker/front/department/index.js @@ -1,83 +1,7 @@ -import ngModule from '../module'; -import Section from 'salix/components/section'; - -class Controller extends Section { - $postLink() { - this.$.treeview.fetch(); - } - - onFetch(item) { - const params = item ? {parentId: item.id} : null; - return this.$.model.applyFilter({}, params).then(() => { - return this.$.model.data; - }); - } - - onSort(a, b) { - return a.name.localeCompare(b.name); - } - - onDrop(dropped, dragged) { - const params = dropped ? {parentId: dropped.id} : null; - const query = `departments/${dragged.id}/moveChild`; - this.$http.post(query, params).then(() => { - this.$.treeview.move(dragged, dropped); - }); - } - - onCreate(parent) { - this.newChild = { - parent: parent, - name: '' - }; - - this.$.createNode.show(); - } - - onCreateDialogOpen() { - this.newChild.name = ''; - } - - onCreateResponse() { - try { - if (!this.newChild.name) - throw new Error(`Name can't be empty`); - - const params = {name: this.newChild.name}; - const parent = this.newChild.parent; - - if (parent && parent.id) - params.parentId = parent.id; - - const query = `departments/createChild`; - this.$http.post(query, params).then(res => { - const item = res.data; - item.parent = parent; - - this.$.treeview.create(item); - }); - } catch (e) { - this.vnApp.showError(this.$t(e.message)); - return false; - } - return true; - } - - onRemove(item) { - this.removedChild = item; - this.$.deleteNode.show(); - } - - onRemoveResponse() { - const childId = this.removedChild.id; - const path = `departments/${childId}/removeChild`; - this.$http.post(path).then(() => { - this.$.treeview.remove(this.removedChild); - }); - } -} - -ngModule.vnComponent('vnWorkerDepartment', { - template: require('./index.html'), - controller: Controller -}); +import './main'; +import './index/'; +import './summary'; +import './card'; +import './descriptor'; +import './basic-data'; +import './descriptor-popover'; diff --git a/modules/worker/front/department/index.html b/modules/worker/front/department/index/index.html similarity index 75% rename from modules/worker/front/department/index.html rename to modules/worker/front/department/index/index.html index df8630104..de77e40a1 100644 --- a/modules/worker/front/department/index.html +++ b/modules/worker/front/department/index/index.html @@ -3,6 +3,14 @@ url="departments/getLeaves" auto-load="false"> + + + +
- {{::item.name}} + + {{::item.name}} +
diff --git a/modules/worker/front/department/index/index.js b/modules/worker/front/department/index/index.js new file mode 100644 index 000000000..118e189e2 --- /dev/null +++ b/modules/worker/front/department/index/index.js @@ -0,0 +1,94 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +class Controller extends Section { + $postLink() { + this.$.treeview.fetch(); + if (this.$params.q) { + const search = JSON.parse(this.$params.q); + this.onSearch(search); + } + } + + onSearch(params) { + this.$.model.applyFilter({}, params).then(() => { + const data = this.$.model.data; + this.$.treeview.data = data; + }); + } + + onFetch(item) { + const params = item ? {parentId: item.id} : null; + return this.$.model.applyFilter({}, params).then(() => { + return this.$.model.data; + }); + } + + onSort(a, b) { + return a.name.localeCompare(b.name); + } + + onDrop(dropped, dragged) { + const params = dropped ? {parentId: dropped.id} : null; + const query = `departments/${dragged.id}/moveChild`; + this.$http.post(query, params).then(() => { + this.$.treeview.move(dragged, dropped); + }); + } + + onCreate(parent) { + this.newChild = { + parent: parent, + name: '' + }; + + this.$.createNode.show(); + } + + onCreateDialogOpen() { + this.newChild.name = ''; + } + + onCreateResponse() { + try { + if (!this.newChild.name) + throw new Error(`Name can't be empty`); + + const params = {name: this.newChild.name}; + const parent = this.newChild.parent; + + if (parent && parent.id) + params.parentId = parent.id; + + const query = `departments/createChild`; + this.$http.post(query, params).then(res => { + const item = res.data; + item.parent = parent; + + this.$.treeview.create(item); + }); + } catch (e) { + this.vnApp.showError(this.$t(e.message)); + return false; + } + return true; + } + + onRemove(item) { + this.removedChild = item; + this.$.deleteNode.show(); + } + + onRemoveResponse() { + const childId = this.removedChild.id; + const path = `departments/${childId}/removeChild`; + this.$http.post(path).then(() => { + this.$.treeview.remove(this.removedChild); + }); + } +} + +ngModule.vnComponent('vnWorkerDepartmentIndex', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/worker/front/department/locale/es.yml b/modules/worker/front/department/locale/es.yml index 74dec0c45..64dfe01ee 100644 --- a/modules/worker/front/department/locale/es.yml +++ b/modules/worker/front/department/locale/es.yml @@ -1,4 +1,5 @@ New department: Nuevo departamento Delete department: Eliminar departamento Are you sure you want to delete it?: ¿Seguro que quieres eliminarlo? -Name can't be empty: El nombre esta vacio \ No newline at end of file +Name can't be empty: El nombre esta vacio +Department workers: Trabajadores del departamento \ No newline at end of file diff --git a/modules/worker/front/department/main/index.html b/modules/worker/front/department/main/index.html new file mode 100644 index 000000000..a1caef294 --- /dev/null +++ b/modules/worker/front/department/main/index.html @@ -0,0 +1,9 @@ + + + + + diff --git a/modules/worker/front/department/main/index.js b/modules/worker/front/department/main/index.js new file mode 100644 index 000000000..cbdf8689d --- /dev/null +++ b/modules/worker/front/department/main/index.js @@ -0,0 +1,7 @@ +import ngModule from '../../module'; +import ModuleMain from 'salix/components/module-main'; + +ngModule.vnComponent('vnWorkerDepartment', { + controller: ModuleMain, + template: require('./index.html') +}); diff --git a/modules/worker/front/department/summary/index.html b/modules/worker/front/department/summary/index.html new file mode 100644 index 000000000..185d024d7 --- /dev/null +++ b/modules/worker/front/department/summary/index.html @@ -0,0 +1,91 @@ + + + + + +
+ {{summary.name}} +
+ + +

+ + Basic data + +

+

+ Basic data +

+
+ + + + + + + + + + + {{summary.worker.user.name}} + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + diff --git a/modules/worker/front/department/summary/index.js b/modules/worker/front/department/summary/index.js new file mode 100644 index 000000000..a9f8ef33a --- /dev/null +++ b/modules/worker/front/department/summary/index.js @@ -0,0 +1,27 @@ +import ngModule from '../../module'; +import Component from 'core/lib/component'; +import './style.scss'; + +class Controller extends Component { + set department(value) { + this._department = value; + this.$.summary = null; + if (!value) return; + this.$.summary = this.department; + } + get department() { + return this._department; + } + + get isHr() { + return this.aclService.hasAny(['hr']); + } +} + +ngModule.component('vnWorkerDepartmentSummary', { + template: require('./index.html'), + controller: Controller, + bindings: { + department: '<' + } +}); diff --git a/modules/worker/front/department/summary/locale/es.yml b/modules/worker/front/department/summary/locale/es.yml new file mode 100644 index 000000000..31073aae8 --- /dev/null +++ b/modules/worker/front/department/summary/locale/es.yml @@ -0,0 +1,12 @@ +Name: Nombre +Code: Código +Chat: Chat +Boss department: Jefe de departamento +Email: Email +Self-consumption customer: Cliente autoconsumo +Telework: Teletrabaja +Notify on errors: Notificar errores +worksInProduction: Pertenece a producción +Fill in days without physical check-ins: Completar días sin registros físicos +Send check-ins by email: Enviar fichadas por mail +Are you sure you want to delete this department?: ¿Estás seguro de que quieres eliminar este departamento? diff --git a/modules/worker/front/department/summary/style.scss b/modules/worker/front/department/summary/style.scss new file mode 100644 index 000000000..7820dbb3c --- /dev/null +++ b/modules/worker/front/department/summary/style.scss @@ -0,0 +1,8 @@ +@import "./variables"; + +vn-worker-department-summary { + .expand { + min-width: 100%; + } +} + diff --git a/modules/worker/front/routes.json b/modules/worker/front/routes.json index 61093a456..7906b1f45 100644 --- a/modules/worker/front/routes.json +++ b/modules/worker/front/routes.json @@ -24,6 +24,9 @@ "description": "Wikipedia" }, {"state": "worker.card.workerLog", "icon": "history"} + ], + "department": [ + {"state": "worker.department.card.basicData", "icon": "settings"} ] }, "keybindings": [ @@ -118,12 +121,35 @@ "worker": "$ctrl.worker" } }, { - "url" : "/department", + "url": "/department?q", "state": "worker.department", "component": "vn-worker-department", - "description": "Departments", - "acl": ["hr"] + "description":"Departments" }, { + "url": "/:id", + "state": "worker.department.card", + "component": "vn-worker-department-card", + "abstract": true, + "description": "Detail" + }, { + "url" : "/summary", + "state": "worker.department.card.summary", + "component": "vn-worker-department-summary", + "description": "Summary", + "params": { + "department": "$ctrl.department" + } + }, + { + "url": "/basic-data", + "state": "worker.department.card.basicData", + "component": "vn-worker-department-basic-data", + "description": "Basic data", + "params": { + "department": "$ctrl.department" + } + }, + { "url": "/dms", "state": "worker.card.dms", "abstract": true, diff --git a/modules/worker/front/summary/index.html b/modules/worker/front/summary/index.html index 72b8e729a..2607d9b2f 100644 --- a/modules/worker/front/summary/index.html +++ b/modules/worker/front/summary/index.html @@ -27,15 +27,19 @@ - + + + {{worker.department.department.name}} + - {{::worker.boss.nickname}} + {{::worker.boss.name}} + + diff --git a/modules/worker/front/summary/index.js b/modules/worker/front/summary/index.js index c2ad107d5..2bb1f0853 100644 --- a/modules/worker/front/summary/index.js +++ b/modules/worker/front/summary/index.js @@ -38,7 +38,7 @@ class Controller extends Summary { }, { relation: 'boss', - scope: {fields: ['id', 'nickname']} + scope: {fields: ['id', 'name']} }, { relation: 'sip', @@ -48,7 +48,8 @@ class Controller extends Summary { relation: 'department', scope: { include: { - relation: 'department' + relation: 'department', + scope: {fields: ['id', 'code', 'name']} } } }