Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2729-prices_popover
This commit is contained in:
commit
9a4c056059
|
@ -30193,7 +30193,7 @@ BEGIN
|
|||
NEW.currencyFk != OLD.currencyFk
|
||||
THEN
|
||||
|
||||
CALL vn2008.recibidaIvaDivisaUpdate(NEW.id);
|
||||
-- CALL vn2008.recibidaIvaDivisaUpdate(NEW.id);
|
||||
|
||||
END IF;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('Client create path', () => {
|
|||
await page.write(selectors.createClientView.taxNumber, '74451390E');
|
||||
await page.write(selectors.createClientView.userName, 'CaptainMarvel');
|
||||
await page.write(selectors.createClientView.email, 'CarolDanvers@verdnatura.es');
|
||||
await page.autocompleteSearch(selectors.createClientView.salesPerson, 'replenisher');
|
||||
await page.autocompleteSearch(selectors.createClientView.salesPerson, 'salesPerson');
|
||||
await page.waitToClick(selectors.createClientView.createButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ describe('Client Edit basicData path', () => {
|
|||
await page.write(selectors.clientBasicData.phone, '333333333');
|
||||
await page.clearInput(selectors.clientBasicData.mobile);
|
||||
await page.write(selectors.clientBasicData.mobile, '444444444');
|
||||
await page.autocompleteSearch(selectors.clientBasicData.salesPerson, 'replenisherNick');
|
||||
await page.autocompleteSearch(selectors.clientBasicData.salesPerson, 'salesPerson');
|
||||
await page.autocompleteSearch(selectors.clientBasicData.channel, 'Metropolis newspaper');
|
||||
await page.waitToClick(selectors.clientBasicData.saveButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
@ -143,7 +143,7 @@ describe('Client Edit basicData path', () => {
|
|||
const result = await page
|
||||
.waitToGetProperty(selectors.clientBasicData.salesPerson, 'value');
|
||||
|
||||
expect(result).toEqual('replenisherNick');
|
||||
expect(result).toEqual('salesPersonNick');
|
||||
});
|
||||
|
||||
it('should now confirm the channel have been selected', async() => {
|
||||
|
|
|
@ -28,10 +28,10 @@
|
|||
<vn-autocomplete
|
||||
disabled="false"
|
||||
ng-model="$ctrl.claim.workerFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithRole"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
where="{role: 'employee'}"
|
||||
where="{role: 'salesPerson'}"
|
||||
label="Attended by">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
ng-model="claimDevelopment.workerFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithInheritedRole"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
|
|
|
@ -25,20 +25,20 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.salesPersonFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithRole"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
where="{role: 'salesPerson'}"
|
||||
label="Salesperson">
|
||||
<tpl-item>{{firstName}} {{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.attenderFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithRole"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
where="{role: 'salesPerson'}"
|
||||
label="Attended by">
|
||||
<tpl-item>{{firstName}} {{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('Client activeWorkersWithRole', () => {
|
||||
it('should return the sales people as result', async() => {
|
||||
let filter = {where: {role: 'salesPerson'}};
|
||||
let result = await app.models.Client.activeWorkersWithRole(filter);
|
||||
|
||||
let isSalesPerson = await app.models.Account.hasRole(result[0].id, 'salesPerson');
|
||||
|
||||
expect(result.length).toEqual(19);
|
||||
expect(isSalesPerson).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return the buyers as result', async() => {
|
||||
let filter = {where: {role: 'buyer'}};
|
||||
let result = await app.models.Client.activeWorkersWithRole(filter);
|
||||
|
||||
let isBuyer = await app.models.Account.hasRole(result[0].id, 'buyer');
|
||||
|
||||
expect(result.length).toEqual(17);
|
||||
expect(isBuyer).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -8,7 +8,6 @@ const LoopBackContext = require('loopback-context');
|
|||
|
||||
module.exports = Self => {
|
||||
// Methods
|
||||
require('../methods/client/activeWorkersWithRole')(Self);
|
||||
require('../methods/client/getCard')(Self);
|
||||
require('../methods/client/createWithUser')(Self);
|
||||
require('../methods/client/listWorkers')(Self);
|
||||
|
|
|
@ -54,11 +54,11 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="$ctrl.client.salesPersonFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithInheritedRole"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
where="{role: 'salesPerson'}"
|
||||
label="Salesperson"
|
||||
vn-acl="salesAssistant">
|
||||
</vn-autocomplete>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.buyerId"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithRole"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
where="{role: 'buyer'}"
|
||||
label="Buyer">
|
||||
<tpl-item>{{nickname}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
<vn-autocomplete
|
||||
label="Salesperson"
|
||||
ng-model="$ctrl.client.salesPersonFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithInheritedRole"
|
||||
search-function="{firstName: $search}"
|
||||
show-field="firstName"
|
||||
where="{role: 'employee'}">
|
||||
where="{role: 'salesPerson'}">
|
||||
<tpl-item>{{firstName}} {{lastName}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.salesPersonFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithInheritedRole"
|
||||
search-function="{firstName: $search}"
|
||||
show-field="firstName"
|
||||
value-field="id"
|
||||
|
|
|
@ -10,76 +10,81 @@ module.exports = Self => {
|
|||
accepts: [
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
type: 'object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'search',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
description: 'Searchs the entry by id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'id',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'The entry id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'created',
|
||||
type: 'Date',
|
||||
type: 'date',
|
||||
description: 'The created date to filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'travelFk',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The travel id to filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'companyFk',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The company to filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'isBooked',
|
||||
type: 'Boolean',
|
||||
type: 'boolean',
|
||||
description: 'The isBokked filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'isConfirmed',
|
||||
type: 'Boolean',
|
||||
type: 'boolean',
|
||||
description: 'The isConfirmed filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'isOrdered',
|
||||
type: 'Boolean',
|
||||
type: 'boolean',
|
||||
description: 'The isOrdered filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'ref',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
description: 'The ref filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'supplierFk',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The supplier id to filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'invoiceInFk',
|
||||
type: 'number',
|
||||
description: 'The invoiceIn id to filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'currencyFk',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The currency id to filter',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'from',
|
||||
type: 'Date',
|
||||
type: 'date',
|
||||
description: `The from date filter`
|
||||
}, {
|
||||
arg: 'to',
|
||||
type: 'Date',
|
||||
type: 'date',
|
||||
description: `The to date filter`
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
|
@ -116,6 +121,7 @@ module.exports = Self => {
|
|||
case 'travelFk':
|
||||
case 'currencyFk':
|
||||
case 'supplierFk':
|
||||
case 'invoiceInFk':
|
||||
param = `e.${param}`;
|
||||
return {[param]: value};
|
||||
}
|
||||
|
|
|
@ -39,11 +39,11 @@
|
|||
<vn-autocomplete
|
||||
disabled="false"
|
||||
ng-model="filter.salesPersonFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithRole"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
where="{role: 'buyer'}"
|
||||
label="Buyer">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -17,7 +17,7 @@ module.exports = Self => {
|
|||
{
|
||||
arg: 'search',
|
||||
type: 'string',
|
||||
description: 'Searchs the invoiceOut by id',
|
||||
description: 'Searchs the invoiceIn by id',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
|
@ -25,6 +25,11 @@ module.exports = Self => {
|
|||
type: 'string',
|
||||
description: 'The supplier reference'
|
||||
},
|
||||
{
|
||||
arg: 'supplierFk',
|
||||
type: 'number',
|
||||
description: 'The supplier id'
|
||||
},
|
||||
{
|
||||
arg: 'fi',
|
||||
type: 'string',
|
||||
|
@ -108,6 +113,7 @@ module.exports = Self => {
|
|||
case 'fi':
|
||||
return {[`s.${param}`]: value};
|
||||
case 'supplierRef':
|
||||
case 'supplierFk':
|
||||
case 'serialNumber':
|
||||
case 'serial':
|
||||
case 'issued':
|
||||
|
@ -132,7 +138,7 @@ module.exports = Self => {
|
|||
ii.isBooked,
|
||||
ii.supplierRef,
|
||||
ii.docFk AS dmsFk,
|
||||
s.id AS supplierFk,
|
||||
ii.supplierFk,
|
||||
s.name AS supplierName,
|
||||
s.account,
|
||||
SUM(iid.amount) AS amount,
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('invoiceIn summary()', () => {
|
||||
it('should return a summary object containing data from one invoiceIn', async() => {
|
||||
const summary = await app.models.InvoiceIn.summary(1);
|
||||
|
||||
expect(summary.supplierRef).toEqual('1234');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,48 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('summary', {
|
||||
description: 'The invoiceIn summary',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'The invoiceIn id',
|
||||
http: {source: 'path'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/summary`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.summary = async id => {
|
||||
const filter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'company',
|
||||
scope: {
|
||||
fields: ['id', 'code']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'supplier',
|
||||
scope: {
|
||||
fields: ['id', 'name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'sageWithholding',
|
||||
scope: {
|
||||
fields: ['withholding']
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
return Self.app.models.InvoiceIn.findById(id, filter);
|
||||
};
|
||||
};
|
|
@ -1,5 +1,8 @@
|
|||
{
|
||||
"InvoiceIn": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"InvoiceInDueDay": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "InvoiceInDueDay",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "invoiceInDueDay"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "number",
|
||||
"description": "Identifier"
|
||||
},
|
||||
"invoiceInFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"dueDated": {
|
||||
"type": "date"
|
||||
},
|
||||
"bankFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"amount": {
|
||||
"type": "number"
|
||||
},
|
||||
"created": {
|
||||
"type": "date"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/invoice-in/filter')(Self);
|
||||
require('../methods/invoice-in/summary')(Self);
|
||||
};
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
"serial": {
|
||||
"type": "string"
|
||||
},
|
||||
"supplierRef": {
|
||||
"type": "string"
|
||||
},
|
||||
"issued": {
|
||||
"type": "date"
|
||||
},
|
||||
|
@ -27,12 +30,18 @@
|
|||
"isBooked": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"isVatDeductible": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"booked": {
|
||||
"type": "date"
|
||||
},
|
||||
"operated": {
|
||||
"type": "date"
|
||||
},
|
||||
"bookEntried": {
|
||||
"type": "date"
|
||||
},
|
||||
"dmsFk": {
|
||||
"type": "number",
|
||||
"mysql": {
|
||||
|
@ -41,6 +50,16 @@
|
|||
}
|
||||
},
|
||||
"relations": {
|
||||
"invoiceInDueDay": {
|
||||
"type": "hasMany",
|
||||
"model": "InvoiceInDueDay",
|
||||
"foreignKey": "invoiceInFk"
|
||||
},
|
||||
"sageWithholding": {
|
||||
"type": "belongsTo",
|
||||
"model": "SageWithholding",
|
||||
"foreignKey": "withholdingSageFk"
|
||||
},
|
||||
"company": {
|
||||
"type": "belongsTo",
|
||||
"model": "Company",
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
<mg-ajax path="InvoiceIns/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.invoiceIn"
|
||||
form="form"
|
||||
save="patch">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="watcher.submit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="Expedition date"
|
||||
ng-model="$ctrl.invoiceIn.issued"
|
||||
vn-focus
|
||||
rule>
|
||||
</vn-date-picker>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="Operation date"
|
||||
ng-model="$ctrl.invoiceIn.operated"
|
||||
rule>
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="$ctrl.invoiceIn.supplierFk"
|
||||
url="Suppliers"
|
||||
show-field="nickname"
|
||||
search-function="{or: [{id: $search}, {nickname: {like: '%'+ $search +'%'}}]}"
|
||||
value-field="id"
|
||||
order="nickname"
|
||||
label="Supplier"
|
||||
required="true"
|
||||
rule>
|
||||
<tpl-item>
|
||||
{{::id}} - {{::nickname}}
|
||||
</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
label="Supplier ref"
|
||||
ng-model="$ctrl.invoiceIn.supplierRef"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="Entry date"
|
||||
ng-model="$ctrl.invoiceIn.bookEntried"
|
||||
rule>
|
||||
</vn-date-picker>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="Accounted date"
|
||||
ng-model="$ctrl.invoiceIn.booked"
|
||||
rule>
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
label="Currency"
|
||||
ng-model="$ctrl.invoiceIn.currencyFk"
|
||||
url="Currencies"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
rule>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
url="Companies"
|
||||
label="Company"
|
||||
show-field="code"
|
||||
value-field="id"
|
||||
ng-model="$ctrl.invoiceIn.companyFk"
|
||||
rule>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
disabled="!watcher.dataChanged()"
|
||||
label="Save">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
class="cancel"
|
||||
label="Undo changes"
|
||||
disabled="!watcher.dataChanged()"
|
||||
ng-click="watcher.loadOriginalData()">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,10 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
ngModule.vnComponent('vnInvoiceInBasicData', {
|
||||
template: require('./index.html'),
|
||||
controller: Section,
|
||||
bindings: {
|
||||
invoiceIn: '<'
|
||||
}
|
||||
});
|
|
@ -3,10 +3,27 @@ import ModuleCard from 'salix/components/module-card';
|
|||
|
||||
class Controller extends ModuleCard {
|
||||
reload() {
|
||||
const filter = {};
|
||||
const filter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'supplier'
|
||||
},
|
||||
{
|
||||
relation: 'invoiceInDueDay'
|
||||
},
|
||||
{
|
||||
relation: 'company'
|
||||
}
|
||||
]};
|
||||
|
||||
this.$http.get(`InvoiceIns/${this.$params.id}`, {filter})
|
||||
.then(res => this.invoiceIn = res.data);
|
||||
.then(res => {
|
||||
this.invoiceIn = res.data;
|
||||
this.invoiceIn.amount = res.data.invoiceInDueDay.reduce(
|
||||
(accumulator, currentValue) => {
|
||||
return accumulator + (currentValue['amount'] || 0);
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,12 @@ import './index.js';
|
|||
describe('vnInvoiceIn', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let data = {id: 1, name: 'fooName'};
|
||||
const expectedAmount = 99;
|
||||
const data = {
|
||||
id: 1,
|
||||
name: 'fooName',
|
||||
invoiceInDueDay: [{amount: expectedAmount}]
|
||||
};
|
||||
|
||||
beforeEach(ngModule('invoiceIn'));
|
||||
|
||||
|
@ -21,7 +26,8 @@ describe('vnInvoiceIn', () => {
|
|||
controller.reload();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.invoiceIn).toEqual(data);
|
||||
expect(controller.invoiceIn).toBeDefined();
|
||||
expect(controller.invoiceIn.amount).toEqual(expectedAmount);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<vn-descriptor-content module="invoiceIn" description="$ctrl.invoiceIn.supplierRef">
|
||||
<slot-menu>
|
||||
<vn-item
|
||||
ng-click="deleteConfirmation.show()"
|
||||
vn-acl="invoicing"
|
||||
vn-acl-action="remove"
|
||||
name="deleteInvoice"
|
||||
translate>
|
||||
Delete Invoice
|
||||
</vn-item>
|
||||
</slot-menu>
|
||||
<slot-body>
|
||||
<div class="attributes">
|
||||
<vn-label-value label="Date" value="{{$ctrl.invoiceIn.issued | date: 'dd/MM/yyyy'}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Booked" value="{{$ctrl.invoiceIn.booked | date: 'dd/MM/yyyy'}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Import" value="{{$ctrl.invoiceIn.amount | currency: 'EUR': 2}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Supplier">
|
||||
<span ng-click="supplierDescriptor.show($event, $ctrl.invoiceIn.supplier.id)" class="link">
|
||||
{{$ctrl.invoiceIn.supplier.nickname}}
|
||||
</span>
|
||||
</vn-label-value>
|
||||
</div>
|
||||
<div class="quicklinks">
|
||||
<div ng-transclude="btnOne">
|
||||
<vn-quick-link tooltip="Supplier" state="['supplier.card.summary', {id: $ctrl.invoiceIn.supplier.id}]"
|
||||
icon="icon-supplier">
|
||||
</vn-quick-link>
|
||||
</div>
|
||||
<div ng-transclude="btnTwo">
|
||||
<vn-quick-link tooltip="Entries list" state="['entry.index', {q: $ctrl.entryFilter}]"
|
||||
icon="icon-entry">
|
||||
</vn-quick-link>
|
||||
</div>
|
||||
<div ng-transclude="btnThree">
|
||||
<vn-quick-link tooltip="Invoice list" state="['invoiceIn.index', {q: $ctrl.invoiceInFilter}]"
|
||||
icon="icon-invoiceIn">
|
||||
</vn-quick-link>
|
||||
</div>
|
||||
</div>
|
||||
</slot-body>
|
||||
</vn-descriptor-content>
|
||||
<vn-confirm vn-id="deleteConfirmation" on-accept="$ctrl.deleteInvoiceIn()"
|
||||
question="Are you sure you want to delete this invoice?">
|
||||
</vn-confirm>
|
||||
<vn-supplier-descriptor-popover vn-id="supplierDescriptor">
|
||||
</vn-supplier-descriptor-popover>
|
|
@ -10,6 +10,26 @@ class Controller extends Descriptor {
|
|||
this.entity = value;
|
||||
}
|
||||
|
||||
get entryFilter() {
|
||||
if (this.invoiceIn)
|
||||
return JSON.stringify({invoiceInFk: this.invoiceIn.id});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
get invoiceInFilter() {
|
||||
if (this.invoiceIn)
|
||||
return JSON.stringify({supplierFk: this.invoiceIn.supplierFk});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
deleteInvoiceIn() {
|
||||
return this.$http.delete(`InvoiceIns/${this.id}`)
|
||||
.then(() => this.$state.go('invoiceIn.index'))
|
||||
.then(() => this.vnApp.showSuccess(this.$t('InvoiceIn deleted')));
|
||||
}
|
||||
|
||||
loadData() {
|
||||
const filter = {
|
||||
include: [
|
||||
|
|
|
@ -6,3 +6,5 @@ import './search-panel';
|
|||
import './card';
|
||||
import './descriptor';
|
||||
import './descriptor-popover';
|
||||
import './summary';
|
||||
import './basic-data';
|
||||
|
|
|
@ -22,26 +22,28 @@
|
|||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<a ng-repeat="invoiceIn in model.data"
|
||||
class="clickable vn-tr search-result">
|
||||
<a
|
||||
ng-repeat="invoiceIn in model.data"
|
||||
class="clickable vn-tr search-result"
|
||||
ui-sref="invoiceIn.card.summary({id: {{::invoiceIn.id}}})">
|
||||
<vn-td>{{::invoiceIn.id}}</vn-td>
|
||||
<vn-td>
|
||||
<span
|
||||
class="link"
|
||||
class="link"
|
||||
vn-click-stop="supplierDescriptor.show($event, invoiceIn.supplierFk)">
|
||||
{{::invoiceIn.supplierName}}
|
||||
</span>
|
||||
</vn-td>
|
||||
</vn-td>
|
||||
<vn-td>{{::invoiceIn.supplierRef | dashIfEmpty}}</vn-td>
|
||||
<vn-td>{{::invoiceIn.serialNumber}}</vn-td>
|
||||
<vn-td>{{::invoiceIn.serial}}</vn-td>
|
||||
<vn-td>{{::invoiceIn.account}}</vn-td>
|
||||
<vn-td>{{::invoiceIn.serialNumber}}</vn-td>
|
||||
<vn-td>{{::invoiceIn.serial}}</vn-td>
|
||||
<vn-td>{{::invoiceIn.account}}</vn-td>
|
||||
<vn-td expand>{{::invoiceIn.issued | date:'dd/MM/yyyy' | dashIfEmpty}}</vn-td>
|
||||
<vn-td center>
|
||||
<vn-check disabled="true"
|
||||
ng-model="invoiceIn.isBooked">
|
||||
</vn-check>
|
||||
</vn-td>
|
||||
</vn-td>
|
||||
<vn-td>{{::invoiceIn.awbCode}}</vn-td>
|
||||
<vn-td>{{::invoiceIn.amount | currency:'EUR'}}</vn-td>
|
||||
<vn-td shrink>
|
||||
|
@ -67,38 +69,6 @@
|
|||
</vn-data-viewer>
|
||||
<vn-popup vn-id="summary">
|
||||
<vn-invoice-in-summary
|
||||
invoice-in="$ctrl.selectedinvoiceIn">
|
||||
invoice-in="$ctrl.selectedInvoiceIn">
|
||||
</vn-invoice-in-summary>
|
||||
</vn-popup>
|
||||
<vn-supplier-descriptor-popover
|
||||
vn-id="supplierDescriptor">
|
||||
</vn-supplier-descriptor-popover>
|
||||
<vn-contextmenu vn-id="contextmenu" targets="['vn-data-viewer']" model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||
<slot-menu>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
ng-click="contextmenu.filterBySelection()">
|
||||
Filter by selection
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
ng-click="contextmenu.excludeSelection()">
|
||||
Exclude selection
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
ng-click="contextmenu.removeFilter()">
|
||||
Remove filter
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-click="contextmenu.removeAllFilters()">
|
||||
Remove all filters
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isActionAllowed()"
|
||||
ng-click="contextmenu.copyValue()">
|
||||
Copy value
|
||||
</vn-item>
|
||||
</slot-menu>
|
||||
</vn-contextmenu>
|
||||
</vn-popup>
|
|
@ -34,6 +34,11 @@ export default class Controller extends Section {
|
|||
|
||||
return [minHour, maxHour];
|
||||
}
|
||||
|
||||
preview(invoiceIn) {
|
||||
this.selectedInvoiceIn = invoiceIn;
|
||||
this.$.summary.show();
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnInvoiceInIndex', {
|
||||
|
|
|
@ -1,2 +1,5 @@
|
|||
InvoiceIn: Facturas recibidas
|
||||
Search invoices in by reference: Buscar facturas recibidas por referencia
|
||||
Search invoices in by reference: Buscar facturas recibidas por referencia
|
||||
Entries list: Listado de entradas
|
||||
Invoice list: Listado de entradas
|
||||
InvoiceIn deleted: Factura eliminada
|
|
@ -7,6 +7,12 @@
|
|||
"menus": {
|
||||
"main": [
|
||||
{"state": "invoiceIn.index", "icon": "icon-invoiceIn"}
|
||||
],
|
||||
"card": [
|
||||
{
|
||||
"state": "invoiceIn.card.basicData",
|
||||
"icon": "settings"
|
||||
}
|
||||
]
|
||||
},
|
||||
"routes": [
|
||||
|
@ -36,9 +42,18 @@
|
|||
"component": "vn-invoice-in-summary",
|
||||
"description": "Summary",
|
||||
"params": {
|
||||
"invoice-In": "$ctrl.invoiceIn"
|
||||
"invoice-in": "$ctrl.invoiceIn"
|
||||
},
|
||||
"acl": ["developer"]
|
||||
"acl": ["administrative"]
|
||||
},
|
||||
{
|
||||
"url": "/basic-data",
|
||||
"state": "invoiceIn.card.basicData",
|
||||
"component": "vn-invoice-in-basic-data",
|
||||
"description": "Basic data",
|
||||
"params": {
|
||||
"invoice-in": "$ctrl.invoiceIn"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<vn-card class="summary">
|
||||
<h5>
|
||||
<a
|
||||
ng-if="::$ctrl.summary.id"
|
||||
vn-tooltip="Go to the Invoice In"
|
||||
ui-sref="invoiceIn.card.summary({id: {{::$ctrl.summary.id}}})"
|
||||
name="goToSummary">
|
||||
<vn-icon-button icon="launch"></vn-icon-button>
|
||||
</a>
|
||||
<span>{{$ctrl.summary.id}} - {{$ctrl.summary.supplier.name}}</span>
|
||||
</h5>
|
||||
<vn-horizontal>
|
||||
<vn-auto>
|
||||
<h4 translate>Basic data</h4>
|
||||
<vn-horizontal>
|
||||
<vn-one>
|
||||
<vn-label-value label="Supplier" value="{{$ctrl.summary.supplier.name}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Supplier ref" value="{{$ctrl.summary.supplierRef}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Doc number" value="{{$ctrl.summary.serial}}/{{$ctrl.summary.serialNumber}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-label-value label="Expedition date" value="{{$ctrl.summary.issued | date: 'dd/MM/yyyy'}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Operation date" value="{{$ctrl.summary.operated | date: 'dd/MM/yyyy'}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Entry date" value="{{$ctrl.summary.bookEntried | date: 'dd/MM/yyyy'}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Booked date" value="{{$ctrl.summary.booked | date: 'dd/MM/yyyy'}}">
|
||||
</vn-label-value>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-label-value label="Sage withholding" value="{{$ctrl.summary.sageWithholding.withholding}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Company" value="{{$ctrl.summary.company.code}}">
|
||||
</vn-label-value>
|
||||
<vn-vertical>
|
||||
<vn-check label="Deductible" ng-model="$ctrl.summary.isVatDeductible" disabled="true">
|
||||
</vn-check>
|
||||
<vn-check label="Booked" ng-model="$ctrl.summary.isBooked" disabled="true">
|
||||
</vn-check>
|
||||
</vn-vertical>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-auto>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-supplier-descriptor-popover
|
||||
vn-id="supplierDescriptor">
|
||||
</vn-supplier-descriptor-popover>
|
|
@ -0,0 +1,28 @@
|
|||
import ngModule from '../module';
|
||||
import Summary from 'salix/components/summary';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Summary {
|
||||
set invoiceIn(value) {
|
||||
this._invoiceIn = value;
|
||||
if (value && value.id)
|
||||
this.getSummary();
|
||||
}
|
||||
|
||||
get invoiceIn() {
|
||||
return this._invoiceIn;
|
||||
}
|
||||
|
||||
getSummary() {
|
||||
return this.$http.get(`InvoiceIns/${this.invoiceIn.id}/summary`)
|
||||
.then(res => this.summary = res.data);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnInvoiceInSummary', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
invoiceIn: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
import './index.js';
|
||||
|
||||
describe('InvoiceIn', () => {
|
||||
describe('Component summary', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let $scope;
|
||||
|
||||
beforeEach(ngModule('invoiceIn'));
|
||||
|
||||
beforeEach(inject(($componentController, _$httpBackend_, $rootScope) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$scope = $rootScope.$new();
|
||||
const $element = angular.element('<vn-invoice-in-summary></vn-invoice-in-summary>');
|
||||
controller = $componentController('vnInvoiceInSummary', {$element, $scope});
|
||||
controller.invoiceIn = {id: 1};
|
||||
}));
|
||||
|
||||
describe('getSummary()', () => {
|
||||
it('should perform a query to set summary', () => {
|
||||
$httpBackend.when('GET', `InvoiceIns/1/summary`).respond(200, 'the data you are looking for');
|
||||
controller.getSummary();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.summary).toEqual('the data you are looking for');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
Go to the Invoice In: Ir a la factura recibida
|
||||
Expedition date: Fecha expedición
|
||||
Operation date: Fecha operación
|
||||
Supplier ref: Ref. proveedor
|
||||
Entry date: Fecha asiento
|
||||
Booked date: Fecha contable
|
||||
Accounted date: Fecha contable
|
||||
Doc number: Numero documento
|
||||
Sage withholding: Retención sage
|
||||
Deductible: Deducible
|
|
@ -0,0 +1,5 @@
|
|||
@import "variables";
|
||||
|
||||
vn-invoice-in-summary .summary {
|
||||
width: $width-lg;
|
||||
}
|
|
@ -44,7 +44,7 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.buyerFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithRolee"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.attenderFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithRole"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
where="{role: 'buyer'}"
|
||||
label="Atender">
|
||||
<tpl-item>{{nickname}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
|
|
|
@ -42,11 +42,11 @@
|
|||
vn-one
|
||||
disabled="false"
|
||||
ng-model="filter.salesPersonFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithRole"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
where="{role: 'buyer'}"
|
||||
label="Buyer">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -28,11 +28,11 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.workerFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithInheritedRole"
|
||||
search-function="{firstName: $search}"
|
||||
show-field="nickname"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
where="{role: 'salesPerson'}"
|
||||
label="Sales person">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="$ctrl.route.workerFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithInheritedRole"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<vn-autocomplete
|
||||
label="Worker"
|
||||
ng-model="$ctrl.route.workerFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithInheritedRole"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
where="{role: 'employee'}">
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.workerFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithInheritedRole"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="$ctrl.supplier.workerFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithInheritedRole"
|
||||
search-function="{firstName: $search}"
|
||||
show-field="nickname"
|
||||
value-field="id"
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.buyerId"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithRole"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
where="{role: 'buyer'}"
|
||||
label="Buyer">
|
||||
<tpl-item>{{nickname}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<vn-autocomplete
|
||||
label="Buyer"
|
||||
ng-model="$ctrl.ticketRequest.attenderFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithRole"
|
||||
show-field="nickname"
|
||||
where="{role: 'buyer'}"
|
||||
search-function="{firstName: $search}">
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.salesPersonFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithInheritedRole"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
url="Clients/activeWorkersWithRole"
|
||||
url="Workers/activeWithInheritedRole"
|
||||
ng-if="$ctrl.isPickerDesignedState"
|
||||
ng-model="$ctrl.workerFk"
|
||||
show-field="nickname"
|
||||
|
|
|
@ -3,26 +3,7 @@ const buildFilter = require('vn-loopback/util/filter').buildFilter;
|
|||
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('activeWorkersWithRole', {
|
||||
description: 'Returns actives workers with salesperson role',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
description: 'Filter defining where and paginated data',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
type: 'Worker',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/activeWorkersWithRole`,
|
||||
verb: 'get'
|
||||
}
|
||||
});
|
||||
|
||||
Self.activeWorkersWithRole = async filter => {
|
||||
Self.activeWorkers = async(query, filter) => {
|
||||
let conn = Self.dataSource.connector;
|
||||
if (filter.where && filter.where.and && Array.isArray(filter.where.and)) {
|
||||
let where = {};
|
||||
|
@ -54,14 +35,8 @@ module.exports = Self => {
|
|||
|
||||
myFilter = mergeFilters(myFilter, clientFilter);
|
||||
|
||||
let stmt = new ParameterizedSQL(
|
||||
`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.role r ON r.id = i.inheritsFrom`
|
||||
);
|
||||
let stmt = new ParameterizedSQL(query);
|
||||
stmt.merge(conn.makeSuffix(myFilter));
|
||||
return await conn.executeStmt(stmt);
|
||||
return conn.executeStmt(stmt);
|
||||
};
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('activeWithInheritedRole', {
|
||||
description: 'Returns active workers with a role',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
description: 'Filter defining where and paginated data',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/activeWithInheritedRole`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.activeWithInheritedRole = async filter => {
|
||||
const query =
|
||||
`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.role r ON r.id = i.inheritsFrom`;
|
||||
|
||||
return Self.activeWorkers(query, filter);
|
||||
};
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('activeWithRole', {
|
||||
description: 'Returns active workers with an inherited role',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
description: 'Filter defining where and paginated data',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/activeWithRole`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.activeWithRole = async filter => {
|
||||
const query =
|
||||
`SELECT DISTINCT w.id, w.firstName, w.lastName, u.name, u.nickname
|
||||
FROM worker w
|
||||
JOIN account.user u ON u.id = w.id
|
||||
JOIN account.role r ON r.id = u.role`;
|
||||
|
||||
return Self.activeWorkers(query, filter);
|
||||
};
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('Worker activeWithInheritedRole', () => {
|
||||
it('should return the workers with an inherited role of salesPerson', async() => {
|
||||
const filter = {where: {role: 'salesPerson'}};
|
||||
const result = await app.models.Worker.activeWithInheritedRole(filter);
|
||||
|
||||
const randomIndex = Math.floor(Math.random() * result.length);
|
||||
const worker = result[randomIndex];
|
||||
|
||||
const isSalesPerson = await app.models.Account.hasRole(worker.id, 'salesPerson');
|
||||
|
||||
expect(result.length).toEqual(19);
|
||||
expect(isSalesPerson).toBe(true);
|
||||
});
|
||||
|
||||
it('should return the workers with an inherited role of buyer', async() => {
|
||||
const filter = {where: {role: 'buyer'}};
|
||||
const result = await app.models.Worker.activeWithInheritedRole(filter);
|
||||
|
||||
const randomIndex = Math.floor(Math.random() * result.length);
|
||||
const worker = result[randomIndex];
|
||||
|
||||
const isBuyer = await app.models.Account.hasRole(worker.id, 'buyer');
|
||||
|
||||
expect(result.length).toEqual(17);
|
||||
expect(isBuyer).toBe(true);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,21 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('Worker activeWithRole', () => {
|
||||
it('should return the sales people as result', async() => {
|
||||
const filter = {where: {role: 'salesPerson'}};
|
||||
const result = await app.models.Worker.activeWithRole(filter);
|
||||
const firstWorker = result[0];
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(firstWorker.nickname).toEqual('salesPersonNick');
|
||||
});
|
||||
|
||||
it('should return the buyers as result', async() => {
|
||||
const filter = {where: {role: 'buyer'}};
|
||||
const result = await app.models.Worker.activeWithRole(filter);
|
||||
const firstWorker = result[0];
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(firstWorker.nickname).toEqual('buyerNick');
|
||||
});
|
||||
});
|
|
@ -7,4 +7,7 @@ module.exports = Self => {
|
|||
require('../methods/worker/createAbsence')(Self);
|
||||
require('../methods/worker/deleteAbsence')(Self);
|
||||
require('../methods/worker/updateAbsence')(Self);
|
||||
require('../methods/worker/active')(Self);
|
||||
require('../methods/worker/activeWithRole')(Self);
|
||||
require('../methods/worker/activeWithInheritedRole')(Self);
|
||||
};
|
||||
|
|
|
@ -30,13 +30,13 @@
|
|||
rule>
|
||||
</vn-textfield>
|
||||
<vn-autocomplete
|
||||
disabled="false"
|
||||
ng-model="$ctrl.worker.bossFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
where="{role: 'employee'}"
|
||||
label="Boss">
|
||||
disabled="false"
|
||||
ng-model="$ctrl.worker.bossFk"
|
||||
url="Clients/activeWorkersWithInheritRole"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
where="{role: 'employee'}"
|
||||
label="Boss">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
|
|
Loading…
Reference in New Issue