diff --git a/db/changes/233601/00-aclWorker.sql b/db/changes/233601/00-aclWorker.sql new file mode 100644 index 000000000..e79d8f738 --- /dev/null +++ b/db/changes/233601/00-aclWorker.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) + VALUES + ('Worker', 'search', 'READ', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/changes/233601/00-department.sql b/db/changes/233601/00-department.sql new file mode 100644 index 000000000..777d26b9f --- /dev/null +++ b/db/changes/233601/00-department.sql @@ -0,0 +1,3 @@ +UPDATE `vn`.`department` + SET code='VN' +WHERE name='VERDNATURA'; diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js index fe3ef08bd..b6ea32a6c 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -632,6 +632,7 @@ let actions = { await this.write(selector, value.toString()); break; case 'vn-autocomplete': + case 'vn-worker-autocomplete': if (value) await this.autocompleteSearch(selector, value.toString()); else @@ -667,6 +668,7 @@ let actions = { switch (tagName) { case 'vn-textfield': case 'vn-autocomplete': + case 'vn-worker-autocomplete': case 'vn-input-time': case 'vn-datalist': el = await input.$('input'); diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 93288efa7..fe3633723 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -187,7 +187,7 @@ export default { country: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.countryFk"]', userName: 'vn-client-create vn-textfield[ng-model="$ctrl.client.userName"]', email: 'vn-client-create vn-textfield[ng-model="$ctrl.client.email"]', - salesPerson: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.salesPersonFk"]', + salesPerson: 'vn-client-create vn-worker-autocomplete[ng-model="$ctrl.client.salesPersonFk"]', saveNewProvicenButton: '#saveProvince', saveNewCityButton: '#saveCity', saveNewPoscode: '#savePostcode', @@ -199,7 +199,7 @@ export default { email: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.email"]', phone: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.phone"]', mobile: 'vn-client-basic-data vn-textfield[ng-model="$ctrl.client.mobile"]', - salesPerson: 'vn-client-basic-data vn-autocomplete[ng-model="$ctrl.client.salesPersonFk"]', + salesPerson: 'vn-client-basic-data vn-worker-autocomplete[ng-model="$ctrl.client.salesPersonFk"]', channel: 'vn-client-basic-data vn-autocomplete[ng-model="$ctrl.client.contactChannelFk"]', transferor: 'vn-client-basic-data vn-autocomplete[ng-model="$ctrl.client.transferorFk"]', businessType: 'vn-client-basic-data vn-autocomplete[ng-model="$ctrl.client.businessTypeFk"]', @@ -735,7 +735,7 @@ export default { }, createStateView: { state: 'vn-autocomplete[ng-model="$ctrl.stateFk"]', - worker: 'vn-autocomplete[ng-model="$ctrl.workerFk"]', + worker: 'vn-worker-autocomplete[ng-model="$ctrl.workerFk"]', saveStateButton: `button[type=submit]` }, claimsIndex: { @@ -781,12 +781,12 @@ export default { firstClaimReason: 'vn-claim-development vn-horizontal:nth-child(1) vn-autocomplete[ng-model="claimDevelopment.claimReasonFk"]', firstClaimResult: 'vn-claim-development vn-horizontal:nth-child(1) vn-autocomplete[ng-model="claimDevelopment.claimResultFk"]', firstClaimResponsible: 'vn-claim-development vn-horizontal:nth-child(1) vn-autocomplete[ng-model="claimDevelopment.claimResponsibleFk"]', - firstClaimWorker: 'vn-claim-development vn-horizontal:nth-child(1) vn-autocomplete[ng-model="claimDevelopment.workerFk"]', + firstClaimWorker: 'vn-claim-development vn-horizontal:nth-child(1) vn-worker-autocomplete[ng-model="claimDevelopment.workerFk"]', firstClaimRedelivery: 'vn-claim-development vn-horizontal:nth-child(1) vn-autocomplete[ng-model="claimDevelopment.claimRedeliveryFk"]', secondClaimReason: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[ng-model="claimDevelopment.claimReasonFk"]', secondClaimResult: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[ng-model="claimDevelopment.claimResultFk"]', secondClaimResponsible: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[ng-model="claimDevelopment.claimResponsibleFk"]', - secondClaimWorker: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[ng-model="claimDevelopment.workerFk"]', + secondClaimWorker: 'vn-claim-development vn-horizontal:nth-child(2) vn-worker-autocomplete[ng-model="claimDevelopment.workerFk"]', secondClaimRedelivery: 'vn-claim-development vn-horizontal:nth-child(2) vn-autocomplete[ng-model="claimDevelopment.claimRedeliveryFk"]', saveDevelopmentButton: 'button[type=submit]' }, @@ -854,7 +854,7 @@ export default { }, createRouteView: { - worker: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.workerFk"]', + worker: 'vn-route-create vn-worker-autocomplete[ng-model="$ctrl.route.workerFk"]', createdDatePicker: 'vn-route-create vn-date-picker[ng-model="$ctrl.route.created"]', vehicleAuto: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.vehicleFk"]', agency: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.agencyModeFk"]', @@ -976,7 +976,7 @@ export default { 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"]', + boss: 'vn-worker-create vn-worker-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"]', createButton: 'vn-worker-create vn-submit[label="Create"]', diff --git a/e2e/paths/05-ticket/05_tracking_state.spec.js b/e2e/paths/05-ticket/05_tracking_state.spec.js index 949c9a8e6..9ac373287 100644 --- a/e2e/paths/05-ticket/05_tracking_state.spec.js +++ b/e2e/paths/05-ticket/05_tracking_state.spec.js @@ -59,7 +59,7 @@ describe('Ticket Create new tracking state path', () => { const result = await page .waitToGetProperty(selectors.createStateView.worker, 'value'); - expect(result).toEqual('salesPersonNick'); + expect(result).toEqual('salesPerson'); }); it(`should succesfully create a valid state`, async() => { diff --git a/front/core/components/autocomplete/index.html b/front/core/components/autocomplete/index.html index 69aac4d43..527ca77e7 100755 --- a/front/core/components/autocomplete/index.html +++ b/front/core/components/autocomplete/index.html @@ -18,7 +18,7 @@ +
- \ No newline at end of file + diff --git a/front/core/components/autocomplete/index.js b/front/core/components/autocomplete/index.js index 2539c4ef4..c78c29398 100755 --- a/front/core/components/autocomplete/index.js +++ b/front/core/components/autocomplete/index.js @@ -17,10 +17,9 @@ import './style.scss'; * @event change Thrown when value is changed */ export default class Autocomplete extends Field { - constructor($element, $, $compile, $transclude) { - super($element, $, $compile); + constructor($element, $, $transclude) { + super($element, $, $transclude); this.$transclude = $transclude; - this.$compile = $compile; this._selection = null; this.input = this.element.querySelector('input'); } @@ -153,7 +152,14 @@ export default class Autocomplete extends Field { filter.include = this.include; let json = encodeURIComponent(JSON.stringify(filter)); - this.$http.get(`${this.url}?filter=${json}`).then( + + let url; + if (this.url.includes('?')) + url = `${this.url}&filter=${json}`; + else + url = `${this.url}?filter=${json}`; + + this.$http.get(url).then( json => this.onSelectionRequest(json.data), () => this.onSelectionRequest() ); @@ -282,7 +288,7 @@ export default class Autocomplete extends Field { this.refreshSelection(); } } -Autocomplete.$inject = ['$element', '$scope', '$compile', '$transclude']; +Autocomplete.$inject = ['$element', '$scope', '$transclude']; ngModule.vnComponent('vnAutocomplete', { template: require('./index.html'), diff --git a/front/core/components/drop-down/index.html b/front/core/components/drop-down/index.html index ab868f7b5..692b0c87c 100644 --- a/front/core/components/drop-down/index.html +++ b/front/core/components/drop-down/index.html @@ -13,12 +13,12 @@ class="dropdown" ng-click="$ctrl.onContainerClick($event)"> -
{{$ctrl.statusText}}
- \ No newline at end of file + diff --git a/front/core/components/field/index.js b/front/core/components/field/index.js index 7ce840555..ff92b6b87 100644 --- a/front/core/components/field/index.js +++ b/front/core/components/field/index.js @@ -3,8 +3,8 @@ import FormInput from '../form-input'; import './style.scss'; export default class Field extends FormInput { - constructor($element, $scope) { - super($element, $scope); + constructor($element, $scope, $transclude) { + super($element, $scope, $transclude); this.prefix = null; this.suffix = null; @@ -197,7 +197,7 @@ export default class Field extends FormInput { }); } } -Field.$inject = ['$element', '$scope']; +Field.$inject = ['$element', '$scope', '$transclude']; ngModule.vnComponent('vnField', { template: require('./index.html'), diff --git a/front/core/components/index.js b/front/core/components/index.js index e1b58374e..eb40d5e1f 100644 --- a/front/core/components/index.js +++ b/front/core/components/index.js @@ -51,6 +51,7 @@ import './textarea'; import './th'; import './treeview'; import './wday-picker'; +import './worker-autocomplete'; import './datalist'; import './contextmenu'; import './rating'; diff --git a/front/core/components/worker-autocomplete/index.html b/front/core/components/worker-autocomplete/index.html new file mode 100755 index 000000000..95631e8aa --- /dev/null +++ b/front/core/components/worker-autocomplete/index.html @@ -0,0 +1,8 @@ + +
+ {{name}} +
+
+ {{nickname}}, {{code}} +
+
diff --git a/front/core/components/worker-autocomplete/index.js b/front/core/components/worker-autocomplete/index.js new file mode 100755 index 000000000..70ca69e6e --- /dev/null +++ b/front/core/components/worker-autocomplete/index.js @@ -0,0 +1,40 @@ +import ngModule from '../../module'; +import Autocomplete from '../autocomplete'; + +export default class WorkerAutocomplete extends Autocomplete { + constructor(...args) { + super(...args); + } + + $onInit() { + super.$onInit(); + + let url = 'Workers/search'; + if (this.departments) { + const parameter = encodeURIComponent(JSON.stringify(this.departments)); + url = `Workers/search?departmentCodes=${parameter}`; + } + Object.assign(this, { + label: 'Worker', + url, + searchFunction: function({$search}) { + return {and: [ + {'active': {neq: false}}, + {or: [ + {'name': $search}, + {'nickname': {like: '%' + $search + '%'}}, + {'code': {like: $search + '%'}} + ]} + ]}; + }, + }); + } +} + +ngModule.vnComponent('vnWorkerAutocomplete', { + slotTemplate: require('./index.html'), + controller: WorkerAutocomplete, + bindings: { + departments: ' { - it('should return false for non-IBAN input', () => { - let isValid = validateIban('Pepinillos'); + it('should return false for invalid Spanish IBAN format', () => { + let isValid = validateIban('ES00 9999 0000 9999 0000 9999', 'ES'); expect(isValid).toBeFalsy(); }); - it('should return false for invalid spanish IBAN input', () => { - let isValid = validateIban('ES00 9999 0000 9999 0000 9999'); - - expect(isValid).toBeFalsy(); - }); - - it('should return true for valid spanish IBAN', () => { - let isValid = validateIban('ES91 2100 0418 4502 0005 1332'); + it('should return true for valid Spanish IBAN', () => { + let isValid = validateIban('ES91 2100 0418 4502 0005 1332', 'ES'); expect(isValid).toBeTruthy(); }); + + it('should return false for invalid Spanish IBAN with incorrect length', () => { + let isValid = validateIban('ES91210004184502000513', 'ES'); + + expect(isValid).toBeFalsy(); + }); + + it('should return false for invalid Spanish IBAN with incorrect module97 result', () => { + let isValid = validateIban('ES9121000418450200051331', 'ES'); + + expect(isValid).toBeFalsy(); + }); + + it('should return true for a non-Spanish countryCode', () => { + let isValid = validateIban('DE89370400440532013000', 'AT'); + + expect(isValid).toBeTruthy(); + }); + + it('should return true for null IBAN', () => { + let isValid = validateIban(null, 'ES'); + + expect(isValid).toBeTruthy(); + }); + + it('should return false for non-string IBAN', () => { + let isValid = validateIban(12345, 'ES'); + + expect(isValid).toBeFalsy(); + }); }); diff --git a/loopback/util/validateIban.js b/loopback/util/validateIban.js index 3ca09ef95..ed3e00426 100644 --- a/loopback/util/validateIban.js +++ b/loopback/util/validateIban.js @@ -1,6 +1,7 @@ -module.exports = function(iban) { +module.exports = function(iban, countryCode) { if (iban == null) return true; if (typeof iban != 'string') return false; + if (countryCode?.toLowerCase() != 'es') return true; iban = iban.toUpperCase(); iban = trim(iban); diff --git a/modules/claim/front/basic-data/index.html b/modules/claim/front/basic-data/index.html index 16e134c60..10aa7623a 100644 --- a/modules/claim/front/basic-data/index.html +++ b/modules/claim/front/basic-data/index.html @@ -25,15 +25,13 @@ - - + - +
@@ -66,16 +66,11 @@ show-field="description" rule> - - + --> - \ No newline at end of file + diff --git a/modules/claim/front/search-panel/index.html b/modules/claim/front/search-panel/index.html index 151a06c8e..fbc527d60 100644 --- a/modules/claim/front/search-panel/index.html +++ b/modules/claim/front/search-panel/index.html @@ -22,26 +22,18 @@ - - {{firstName}} {{name}} - - + - {{firstName}} {{name}} - + { }); async function ibanNeedsValidation(err, done) { - const filter = { - fields: ['code'], - where: {id: this.countryFk} - }; - const country = await Self.app.models.Country.findOne(filter); - const code = country ? country.code.toLowerCase() : null; - if (code != 'es') + if (!this.bankEntityFk) return done(); - if (!validateIban(this.iban)) + const bankEntity = await Self.app.models.BankEntity.findById(this.bankEntityFk); + const filter = { + fields: ['code'], + where: {id: bankEntity.countryFk} + }; + const country = await Self.app.models.Country.findOne(filter); + + if (!validateIban(this.iban, country?.code)) err(); done(); } diff --git a/modules/client/front/basic-data/index.html b/modules/client/front/basic-data/index.html index a5c866979..e48b39fdc 100644 --- a/modules/client/front/basic-data/index.html +++ b/modules/client/front/basic-data/index.html @@ -14,13 +14,13 @@ - @@ -59,18 +59,15 @@ - - - + - {{nickname}} diff --git a/modules/client/front/create/index.html b/modules/client/front/create/index.html index 3e7fdd949..e6bf561ef 100644 --- a/modules/client/front/create/index.html +++ b/modules/client/front/create/index.html @@ -15,18 +15,15 @@ rule vn-focus> - - {{firstName}} {{lastName}} - + departments="['VT']" + show-field="nickname"> + - - {{code}} - {{town.name}} ({{town.province.name}}, + {{code}} - {{town.name}} ({{town.province.name}}, {{town.province.country.country}}) @@ -82,7 +79,7 @@ - {{name}}, {{province.name}} + {{name}}, {{province.name}} ({{province.country.country}}) @@ -150,4 +147,4 @@ - \ No newline at end of file + diff --git a/modules/client/front/search-panel/index.html b/modules/client/front/search-panel/index.html index a02f93882..2105d3a65 100644 --- a/modules/client/front/search-panel/index.html +++ b/modules/client/front/search-panel/index.html @@ -14,17 +14,12 @@ vn-one label="Name" ng-model="filter.name"> - - {{firstName}} {{name}} - + diff --git a/modules/item/front/fixed-price-search-panel/index.html b/modules/item/front/fixed-price-search-panel/index.html index ebe210277..347e65571 100644 --- a/modules/item/front/fixed-price-search-panel/index.html +++ b/modules/item/front/fixed-price-search-panel/index.html @@ -54,11 +54,10 @@ vn-id="buyer" disabled="false" ng-model="$ctrl.filter.buyerFk" - url="Workers/activeWithRole" + url="TicketRequests/getItemTypeWorker" show-field="nickname" search-function="{firstName: $search}" value-field="id" - where="{role: {inq: ['logistic', 'buyer']}}" label="Buyer" on-change="$ctrl.addFilters()"> diff --git a/modules/item/front/index/index.js b/modules/item/front/index/index.js index 10bd4bbb7..2bcc2302a 100644 --- a/modules/item/front/index/index.js +++ b/modules/item/front/index/index.js @@ -44,8 +44,7 @@ class Controller extends Section { { field: 'buyerFk', autocomplete: { - url: 'Workers/activeWithRole', - where: `{role: {inq: ['logistic', 'buyer']}}`, + url: 'TicketRequests/getItemTypeWorker', searchFunction: '{firstName: $search}', showField: 'nickname', valueField: 'id', diff --git a/modules/item/front/request-search-panel/index.html b/modules/item/front/request-search-panel/index.html index 9d35fbca4..6a51a429d 100644 --- a/modules/item/front/request-search-panel/index.html +++ b/modules/item/front/request-search-panel/index.html @@ -22,12 +22,11 @@ - {{nickname}} + label="Atender"> @@ -46,18 +45,13 @@ - - {{firstName}} {{lastName}} - + departments="['VT']" + label="Salesperson"> + -
@@ -43,16 +43,12 @@ label="Nickname" ng-model="filter.nickname"> - - {{firstName}} {{name}} - + - - + - \ No newline at end of file + diff --git a/modules/route/front/basic-data/index.html b/modules/route/front/basic-data/index.html index ade9230e8..7f9aef0d0 100644 --- a/modules/route/front/basic-data/index.html +++ b/modules/route/front/basic-data/index.html @@ -8,20 +8,11 @@
- - -
{{::nickname}}
-
{{::name}}
-
-
+ - - + show-field="nickname"> + diff --git a/modules/route/front/search-panel/index.html b/modules/route/front/search-panel/index.html index a78d88d1c..f3d392580 100644 --- a/modules/route/front/search-panel/index.html +++ b/modules/route/front/search-panel/index.html @@ -1,7 +1,7 @@
@@ -15,16 +15,11 @@ - - + show-field="nickname"> + { }); async function ibanValidation(err, done) { - const supplier = await Self.app.models.Supplier.findById(this.supplierFk); + if (!this.bankEntityFk) + return done(); + + const bankEntity = await Self.app.models.BankEntity.findById(this.bankEntityFk); const filter = { fields: ['code'], - where: {id: supplier.countryFk} + where: {id: bankEntity.countryFk} }; const country = await Self.app.models.Country.findOne(filter); - const code = country ? country.code.toLowerCase() : null; - if (code != 'es') - return done(); - if (!validateIban(this.iban)) + if (!validateIban(this.iban, country?.code)) err(); done(); } diff --git a/modules/supplier/front/basic-data/index.html b/modules/supplier/front/basic-data/index.html index 9991908d4..68e635a06 100644 --- a/modules/supplier/front/basic-data/index.html +++ b/modules/supplier/front/basic-data/index.html @@ -15,29 +15,25 @@ rule vn-focus> - - + @@ -45,7 +41,7 @@ @@ -63,4 +59,4 @@ ng-click="watcher.loadOriginalData()"> - \ No newline at end of file + diff --git a/modules/supplier/front/consumption-search-panel/index.html b/modules/supplier/front/consumption-search-panel/index.html index 597c6edab..5cba11d3c 100644 --- a/modules/supplier/front/consumption-search-panel/index.html +++ b/modules/supplier/front/consumption-search-panel/index.html @@ -17,12 +17,11 @@ - {{nickname}} diff --git a/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js b/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js index 9ea859f7c..f160cfaac 100644 --- a/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js +++ b/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js @@ -22,9 +22,13 @@ module.exports = Self => { } }); - Self.getItemTypeWorker = async filter => { + Self.getItemTypeWorker = async(filter, options) => { + const myOptions = {}; const conn = Self.dataSource.connector; + if (typeof options == 'object') + Object.assign(myOptions, options); + const query = `SELECT DISTINCT u.id, u.nickname FROM itemType it diff --git a/modules/ticket/front/search-panel/index.html b/modules/ticket/front/search-panel/index.html index 52bede97f..d80f21531 100644 --- a/modules/ticket/front/search-panel/index.html +++ b/modules/ticket/front/search-panel/index.html @@ -1,7 +1,7 @@
@@ -62,16 +62,12 @@ label="Nickname" ng-model="filter.nickname"> - - {{firstName}} {{name}} - + - - + ng-model="$ctrl.workerFk"> + @@ -43,4 +36,4 @@ ui-sref="ticket.card.tracking.index"> - \ No newline at end of file + diff --git a/modules/worker/back/methods/worker/activeWithInheritedRole.js b/modules/worker/back/methods/worker/activeWithInheritedRole.js index 9536b0f29..19038405b 100644 --- a/modules/worker/back/methods/worker/activeWithInheritedRole.js +++ b/modules/worker/back/methods/worker/activeWithInheritedRole.js @@ -1,7 +1,7 @@ module.exports = Self => { Self.remoteMethod('activeWithInheritedRole', { - description: 'Returns active workers with a role', + description: 'Returns active workers with an inherited role', accessType: 'READ', accepts: [{ arg: 'filter', @@ -24,7 +24,7 @@ module.exports = Self => { `SELECT DISTINCT w.id, w.firstName, w.lastName, u.name, u.nickname FROM worker w JOIN account.user u ON u.id = w.userFk - JOIN account.roleRole i ON i.role = u.role + JOIN account.roleRole i ON i.role = u.role JOIN account.role r ON r.id = i.inheritsFrom`; return Self.activeWorkers(query, filter); diff --git a/modules/worker/back/methods/worker/activeWithRole.js b/modules/worker/back/methods/worker/activeWithRole.js index 392416458..c7f96e151 100644 --- a/modules/worker/back/methods/worker/activeWithRole.js +++ b/modules/worker/back/methods/worker/activeWithRole.js @@ -1,7 +1,7 @@ module.exports = Self => { Self.remoteMethod('activeWithRole', { - description: 'Returns active workers with an inherited role', + description: 'Returns active workers with a role', accessType: 'READ', accepts: [{ arg: 'filter', diff --git a/modules/worker/back/methods/worker/search.js b/modules/worker/back/methods/worker/search.js new file mode 100644 index 000000000..cd0a466ea --- /dev/null +++ b/modules/worker/back/methods/worker/search.js @@ -0,0 +1,69 @@ +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const mergeFilters = require('vn-loopback/util/filter').mergeFilters; + +module.exports = Self => { + Self.remoteMethodCtx('search', { + description: 'Returns an array of search results for a specified worker', + accepts: [{ + arg: 'filter', + type: 'object', + description: 'Filter to define conditions and paginate the data.', + required: true + }, + { + arg: 'departmentCodes', + type: ['string'], + description: 'Department codes to search workers', + }], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/search`, + verb: 'GET' + } + }); + + Self.search = async(ctx, filter, departmentCodes) => { + const models = Self.app.models; + const conn = Self.dataSource.connector; + + if (departmentCodes) { + const departments = await models.Department.find({ + fields: ['id', 'sons'], + where: {code: {inq: departmentCodes}} + }); + + const allLeaves = await getAllLeaves(ctx, departments); + const where = {'departmentFk': {inq: allLeaves}}; + filter = mergeFilters(filter, {where}); + } + + const stmt = new ParameterizedSQL(` + SELECT * + FROM( + SELECT DISTINCT w.id, w.code, u.name, u.nickname, u.active, b.departmentFk + FROM worker w + JOIN account.user u ON u.id = w.id + JOIN business b ON b.workerFk = w.id + ) w`); + + stmt.merge(conn.makeSuffix(filter)); + return conn.executeStmt(stmt); + }; + + async function getAllLeaves(ctx, departments) { + const models = Self.app.models; + const leaves = []; + for (const department of departments) { + if (department.sons > 0) { + const subLeaves = await models.Department.getLeaves(ctx, department.id, null); + const grandLeaves = await getAllLeaves(ctx, subLeaves); + leaves.push(...grandLeaves); + } + leaves.push(department.id); + } + return leaves; + } +}; diff --git a/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js index b44703a88..ccae3a6e6 100644 --- a/modules/worker/back/models/worker.js +++ b/modules/worker/back/models/worker.js @@ -16,6 +16,7 @@ module.exports = Self => { require('../methods/worker/new')(Self); require('../methods/worker/deallocatePDA')(Self); require('../methods/worker/allocatePDA')(Self); + require('../methods/worker/search')(Self); require('../methods/worker/isAuthorized')(Self); Self.validatesUniquenessOf('locker', { diff --git a/modules/worker/front/basic-data/index.html b/modules/worker/front/basic-data/index.html index d89d88f2e..2d85d018d 100644 --- a/modules/worker/front/basic-data/index.html +++ b/modules/worker/front/basic-data/index.html @@ -37,14 +37,11 @@
- - + - - + - - + - + @@ -78,12 +76,12 @@ label="Fill in days without physical check-ins" ng-model="$ctrl.department.hasToRefill"> - - + + - +