Merge branch 'dev' into 5216-expeditionStateAdd
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Jorge Penadés 2023-08-25 12:43:26 +00:00
commit 5fe12d9281
44 changed files with 309 additions and 231 deletions

View File

@ -0,0 +1,3 @@
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES
('Worker', 'search', 'READ', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,3 @@
UPDATE `vn`.`department`
SET code='VN'
WHERE name='VERDNATURA';

View File

@ -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');

View File

@ -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"]',

View File

@ -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() => {

View File

@ -18,7 +18,7 @@
<label>
<span translate>{{$ctrl.label}}</span>
<span class="required">*</span>
</label>
</label>
</div>
<div class="icons pre">
<vn-icon
@ -50,4 +50,4 @@
on-select="$ctrl.onDropDownSelect(item)"
on-data-ready="$ctrl.onDataReady()"
on-close-start="$ctrl.onDropDownClose()">
</vn-drop-down>
</vn-drop-down>

View File

@ -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'),

View File

@ -13,12 +13,12 @@
class="dropdown"
ng-click="$ctrl.onContainerClick($event)">
</ul>
<div
ng-if="$ctrl.statusText"
<div
ng-if="$ctrl.statusText"
ng-click="$ctrl.onLoadMoreClick($event)"
class="status"
translate>
{{$ctrl.statusText}}
</div>
</div>
</default>
</default>

View File

@ -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'),

View File

@ -51,6 +51,7 @@ import './textarea';
import './th';
import './treeview';
import './wday-picker';
import './worker-autocomplete';
import './datalist';
import './contextmenu';
import './rating';

View File

@ -0,0 +1,8 @@
<tpl-item>
<div>
{{name}}
</div>
<div class="text-caption text-secondary">
{{nickname}}, {{code}}
</div>
</tpl-item>

View File

@ -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: '<?'
},
});

View File

@ -1,21 +1,45 @@
const validateIban = require('../validateIban');
describe('IBAN validation', () => {
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();
});
});

View File

@ -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);

View File

@ -25,15 +25,13 @@
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
<vn-worker-autocomplete
disabled="false"
ng-model="$ctrl.claim.workerFk"
url="Workers/activeWithRole"
show-field="nickname"
search-function="{firstName: $search}"
where="{role: 'salesPerson'}"
ng-model="$ctrl.claim.workerFk"
departments="['VT']"
label="Attended by">
</vn-autocomplete>
</vn-worker-autocomplete>
<vn-autocomplete
ng-model="$ctrl.claim.claimStateFk"
data="claimStates"

View File

@ -36,7 +36,7 @@
data="claimDevelopments"
form="form">
</vn-watcher>
<vn-vertical class="vn-w-md">
<vn-vertical class="vn-w-lg">
<vn-card class="vn-pa-lg">
<vn-vertical>
<form name="form">
@ -66,16 +66,11 @@
show-field="description"
rule>
</vn-autocomplete>
<vn-autocomplete
<vn-worker-autocomplete
ng-model="claimDevelopment.workerFk"
url="Workers/activeWithInheritedRole"
show-field="nickname"
search-function="{firstName: $search}"
value-field="id"
where="{role: 'employee'}"
label="Worker"
rule>
</vn-autocomplete>
</vn-worker-autocomplete>
<vn-autocomplete
label="Redelivery"
ng-model="claimDevelopment.claimRedeliveryFk"
@ -118,4 +113,4 @@
ng-click="watcher.loadOriginalData()">
</vn-button> -->
</vn-button-bar>
</vn-vertical>
</vn-vertical>

View File

@ -22,26 +22,18 @@
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
<vn-worker-autocomplete
vn-one
ng-model="filter.salesPersonFk"
url="Workers/activeWithRole"
search-function="{firstName: $search}"
value-field="id"
where="{role: {inq: ['salesTeamBoss', 'salesPerson', 'officeBoss']}}"
departments="['VT']"
label="Salesperson">
<tpl-item>{{firstName}} {{name}}</tpl-item>
</vn-autocomplete>
<vn-autocomplete
</vn-worker-autocomplete>
<vn-worker-autocomplete
vn-one
ng-model="filter.attenderFk"
url="Workers/activeWithRole"
search-function="{firstName: $search}"
value-field="id"
where="{role: {inq: ['salesTeamBoss', 'salesPerson']}}"
departments="['VT']"
label="Attended by">
<tpl-item>{{firstName}} {{name}}</tpl-item>
</vn-autocomplete>
</vn-worker-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete vn-one

View File

@ -90,16 +90,17 @@ module.exports = Self => {
});
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();
}

View File

@ -14,13 +14,13 @@
<vn-card class="vn-pa-lg">
<vn-horizontal>
<vn-textfield
vn-one
label="Comercial Name"
vn-one
label="Comercial Name"
ng-model="$ctrl.client.name"
rule
vn-focus>
</vn-textfield>
<vn-autocomplete
<vn-autocomplete
vn-one
ng-model="$ctrl.client.businessTypeFk"
url="BusinessTypes"
@ -37,8 +37,8 @@
rule>
</vn-textfield>
<vn-textfield
vn-one
label="Email"
vn-one
label="Email"
ng-model="$ctrl.client.email"
rule
info="You can save multiple emails">
@ -59,18 +59,15 @@
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
<vn-worker-autocomplete
vn-one
ng-model="$ctrl.client.salesPersonFk"
url="Workers/activeWithInheritedRole"
departments="['VT']"
show-field="nickname"
search-function="{firstName: $search}"
value-field="id"
where="{role: 'salesPerson'}"
label="Salesperson"
vn-acl="salesAssistant">
</vn-autocomplete>
<vn-autocomplete
</vn-worker-autocomplete>
<vn-autocomplete
vn-one
ng-model="$ctrl.client.contactChannelFk"
data="contactChannels"

View File

@ -17,12 +17,11 @@
<vn-autocomplete
vn-one
ng-model="filter.buyerId"
url="Workers/activeWithRole"
url="TicketRequests/getItemTypeWorker"
search-function="{firstName: $search}"
show-field="nickname"
value-field="id"
where="{role: {inq: ['logistic', 'buyer']}}"
label="Buyer">
<tpl-item>{{nickname}}</tpl-item>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>

View File

@ -15,18 +15,15 @@
rule
vn-focus>
</vn-textfield>
<vn-autocomplete
<vn-worker-autocomplete
label="Salesperson"
ng-model="$ctrl.client.salesPersonFk"
url="Workers/activeWithInheritedRole"
search-function="{firstName: $search}"
show-field="firstName"
where="{role: 'salesPerson'}">
<tpl-item>{{firstName}} {{lastName}}</tpl-item>
</vn-autocomplete>
departments="['VT']"
show-field="nickname">
</vn-worker-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
<vn-autocomplete
vn-id="businessTypeFk"
ng-model="$ctrl.client.businessTypeFk"
url="BusinessTypes"
@ -68,7 +65,7 @@
show-field="code"
rule>
<tpl-item>
{{code}} - {{town.name}} ({{town.province.name}},
{{code}} - {{town.name}} ({{town.province.name}},
{{town.province.country.country}})
</tpl-item>
<append>
@ -82,7 +79,7 @@
</append>
</vn-datalist>
<vn-datalist
vn-id="town"
vn-id="town"
label="City"
ng-model="$ctrl.client.city"
selection="$ctrl.town"
@ -90,7 +87,7 @@
fields="['id', 'name', 'provinceFk']"
value-field="name">
<tpl-item>
{{name}}, {{province.name}}
{{name}}, {{province.name}}
({{province.country.country}})
</tpl-item>
</vn-datalist>
@ -150,4 +147,4 @@
<vn-geo-postcode
vn-id="postcode"
on-response="$ctrl.onResponse($response)">
</vn-geo-postcode>
</vn-geo-postcode>

View File

@ -14,17 +14,12 @@
vn-one label="Name"
ng-model="filter.name">
</vn-textfield>
<vn-autocomplete
<vn-worker-autocomplete
vn-one
ng-model="filter.salesPersonFk"
url="Workers/activeWithInheritedRole"
search-function="{firstName: $search}"
show-field="firstName"
value-field="id"
where="{role: 'salesPerson'}"
departments="['VT']"
label="Salesperson">
<tpl-item>{{firstName}} {{name}}</tpl-item>
</vn-autocomplete>
</vn-worker-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-textfield

View File

@ -54,11 +54,10 @@
vn-id="salesPerson"
disabled="false"
ng-model="$ctrl.filter.salesPersonFk"
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()">
</vn-autocomplete>

View File

@ -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()">
</vn-autocomplete>

View File

@ -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',

View File

@ -22,12 +22,11 @@
<vn-autocomplete
vn-one
ng-model="filter.attenderFk"
url="Workers/activeWithRole"
url="TicketRequests/getItemTypeWorker"
search-function="{firstName: $search}"
show-field="nickname"
value-field="id"
where="{role: {inq: ['logistic', 'buyer']}}"
label="Buyer">
<tpl-item>{{nickname}}</tpl-item>
label="Atender">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal class="vn-px-lg">
@ -46,18 +45,13 @@
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal class="vn-px-lg">
<vn-autocomplete
<vn-worker-autocomplete
vn-one
ng-model="filter.requesterFk"
url="Workers/activeWithInheritedRole"
search-function="{firstName: $search}"
value-field="id"
where="{role: 'salesPerson'}"
label="Comercial">
<tpl-item>{{firstName}} {{lastName}}</tpl-item>
</vn-autocomplete>
departments="['VT']"
label="Salesperson">
</vn-worker-autocomplete>
</vn-horizontal>
<section class="vn-px-md">
<vn-horizontal class="manifold-panel vn-pa-md">
<vn-date-picker

View File

@ -1,7 +1,7 @@
<div class="search-panel">
<vn-crud-model
auto-load="true"
url="Warehouses"
auto-load="true"
url="Warehouses"
data="warehouses">
</vn-crud-model>
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
@ -43,16 +43,12 @@
label="Nickname"
ng-model="filter.nickname">
</vn-textfield>
<vn-autocomplete
<vn-worker-autocomplete
vn-one
ng-model="filter.salesPersonFk"
url="Workers/activeWithInheritedRole"
search-function="{firstName: $search}"
value-field="id"
where="{role: 'employee'}"
departments="['VT']"
label="Sales person">
<tpl-item>{{firstName}} {{name}}</tpl-item>
</vn-autocomplete>
</vn-worker-autocomplete>
<vn-textfield
vn-one
label="Invoice"

View File

@ -25,16 +25,13 @@
show-field="name"
value-field="id">
</vn-autocomplete>
<vn-autocomplete
<vn-worker-autocomplete
vn-one
ng-model="filter.workerFk"
url="Workers/activeWithInheritedRole"
search-function="{firstName: $search}"
departments="['VT']"
show-field="nickname"
value-field="id"
where="{role: 'salesPerson'}"
label="Sales person">
</vn-autocomplete>
</vn-worker-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-date-picker
@ -86,4 +83,4 @@
<vn-submit label="Search"></vn-submit>
</vn-horizontal>
</form>
</div>
</div>

View File

@ -8,20 +8,11 @@
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
<vn-card class="vn-pa-lg">
<vn-horizontal>
<vn-autocomplete
<vn-worker-autocomplete
ng-model="$ctrl.route.workerFk"
url="Workers/activeWithInheritedRole"
show-field="nickname"
search-function="{firstName: $search}"
value-field="id"
where="{role: 'employee'}"
label="Worker"
vn-name="worker">
<tpl-item>
<div>{{::nickname}}</div>
<div class="text-secondary text-caption">{{::name}}</div>
</tpl-item>
</vn-autocomplete>
</vn-worker-autocomplete>
<vn-autocomplete
label="Vehicle"
ng-model="$ctrl.route.vehicleFk"

View File

@ -8,16 +8,12 @@
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
<vn-card class="vn-pa-lg">
<vn-horizontal>
<vn-autocomplete
label="Worker"
<vn-worker-autocomplete
ng-model="$ctrl.route.workerFk"
url="Workers/activeWithInheritedRole"
show-field="nickname"
search-function="{firstName: $search}"
where="{role: 'employee'}">
</vn-autocomplete>
show-field="nickname">
</vn-worker-autocomplete>
<vn-date-picker
label="Created"
label="Created"
ng-model="$ctrl.route.created">
</vn-date-picker>
</vn-horizontal>

View File

@ -1,7 +1,7 @@
<div class="search-panel">
<vn-crud-model
auto-load="true"
url="Warehouses"
auto-load="true"
url="Warehouses"
data="warehouses">
</vn-crud-model>
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
@ -15,16 +15,11 @@
</vn-textfield>
</vn-horizontal>
<vn-horizontal class="vn-px-lg">
<vn-autocomplete
<vn-worker-autocomplete
vn-one
ng-model="filter.workerFk"
url="Workers/activeWithInheritedRole"
show-field="nickname"
search-function="{firstName: $search}"
value-field="id"
where="{role: 'employee'}"
label="Worker">
</vn-autocomplete>
show-field="nickname">
</vn-worker-autocomplete>
<vn-autocomplete
vn-one
label="Agency"

View File

@ -7,18 +7,18 @@ module.exports = Self => {
});
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();
}

View File

@ -15,29 +15,25 @@
rule
vn-focus>
</vn-textfield>
<vn-autocomplete
<vn-worker-autocomplete
vn-one
ng-model="$ctrl.supplier.workerFk"
url="Workers/activeWithInheritedRole"
search-function="{firstName: $search}"
show-field="nickname"
value-field="id"
where="{role: 'employee'}"
label="Responsible"
info="Responsible for approving invoices">
</vn-autocomplete>
</vn-worker-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-check
label="Verified"
label="Verified"
ng-model="$ctrl.supplier.isSerious">
</vn-check>
<vn-check
label="Active"
label="Active"
ng-model="$ctrl.supplier.isActive">
</vn-check>
<vn-check
label="PayMethodChecked"
label="PayMethodChecked"
ng-model="$ctrl.supplier.isPayMethodChecked"
vn-acl="financial">
</vn-check>
@ -45,7 +41,7 @@
<vn-horizontal>
<vn-textarea
vn-one
label="Notes"
label="Notes"
ng-model="$ctrl.supplier.note"
rule>
</vn-textarea>
@ -63,4 +59,4 @@
ng-click="watcher.loadOriginalData()">
</vn-button>
</vn-button-bar>
</form>
</form>

View File

@ -17,12 +17,11 @@
<vn-autocomplete
vn-one
ng-model="filter.buyerId"
url="Workers/activeWithRole"
url="TicketRequests/getItemTypeWorker"
search-function="{firstName: $search}"
show-field="nickname"
value-field="id"
where="{role: {inq: ['logistic', 'buyer']}}"
label="Buyer">
<tpl-item>{{nickname}}</tpl-item>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>

View File

@ -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

View File

@ -1,7 +1,7 @@
<div class="search-panel">
<vn-crud-model
auto-load="true"
url="Warehouses"
auto-load="true"
url="Warehouses"
data="warehouses">
</vn-crud-model>
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
@ -62,16 +62,12 @@
label="Nickname"
ng-model="filter.nickname">
</vn-textfield>
<vn-autocomplete
<vn-worker-autocomplete
vn-one
ng-model="filter.salesPersonFk"
url="Workers/activeWithInheritedRole"
search-function="{firstName: $search}"
value-field="id"
where="{role: 'employee'}"
departments="['VT']"
label="Sales person">
<tpl-item>{{firstName}} {{name}}</tpl-item>
</vn-autocomplete>
</vn-worker-autocomplete>
<vn-textfield
vn-one
label="Invoice"

View File

@ -14,22 +14,15 @@
<vn-horizontal>
<vn-autocomplete
vn-one
ng-model="$ctrl.stateFk"
ng-model="$ctrl.stateFk"
data="states"
label="State"
vn-focus>
</vn-autocomplete>
<vn-autocomplete
<vn-worker-autocomplete
vn-one
url="Workers/activeWithInheritedRole"
ng-if="$ctrl.isPickerDesignedState"
ng-model="$ctrl.workerFk"
show-field="nickname"
search-function="{firstName: $search}"
value-field="id"
where="{role: 'employee'}"
label="Worker">
</vn-autocomplete>
ng-model="$ctrl.workerFk">
</vn-worker-autocomplete>
</vn-horizontal>
</vn-card>
<vn-button-bar>
@ -43,4 +36,4 @@
ui-sref="ticket.card.tracking.index">
</vn-button>
</vn-button-bar>
</form>
</form>

View File

@ -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);

View File

@ -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',

View File

@ -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;
}
};

View File

@ -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', {

View File

@ -37,14 +37,11 @@
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
<vn-worker-autocomplete
ng-model="$ctrl.worker.bossFk"
url="Workers/activeWithInheritedRole"
show-field="nickname"
search-function="{firstName: $search}"
where="{role: 'employee'}"
label="Boss">
</vn-autocomplete>
</vn-worker-autocomplete>
<vn-autocomplete
label="Marital status"
data="$ctrl.maritalStatus"

View File

@ -131,15 +131,12 @@
value-field="id"
label="Company">
</vn-autocomplete>
<vn-autocomplete
<vn-worker-autocomplete
vn-one
ng-model="$ctrl.worker.bossFk"
url="Workers/activeWithInheritedRole"
show-field="nickname"
search-function="{firstName: $search}"
where="{role: 'employee'}"
label="Boss">
</vn-autocomplete>
</vn-worker-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete

View File

@ -44,13 +44,11 @@
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
<vn-worker-autocomplete
ng-model="$ctrl.department.workerFk"
url="Workers/activeWithInheritedRole"
show-field="nickname"
search-function="{firstName: $search}"
label="Boss department">
</vn-autocomplete>
</vn-worker-autocomplete>
<vn-autocomplete
ng-model="$ctrl.department.clientFk"
url="Clients/"
@ -69,7 +67,7 @@
ng-model="$ctrl.department.hasToMistake">
</vn-check>
</vn-horizontal>
<vn-horizontal>
<vn-horizontal>
<vn-check
label="worksInProduction"
ng-model="$ctrl.department.isProduction">
@ -78,12 +76,12 @@
label="Fill in days without physical check-ins"
ng-model="$ctrl.department.hasToRefill">
</vn-check>
</vn-horizontal>
<vn-horizontal>
</vn-horizontal>
<vn-horizontal>
<vn-check
label="Send check-ins by email"
ng-model="$ctrl.department.hasToSendMail">
</vn-check>
</vn-check>
</vn-horizontal>
</vn-vertical>
</vn-card>