Merge branch 'dev' of https://git.verdnatura.es/salix into dev
This commit is contained in:
commit
0ffa39e55b
|
@ -4,7 +4,9 @@
|
|||
{
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"name": "Attach"
|
||||
"name": "Attach",
|
||||
"restart": true,
|
||||
"timeout": 50000
|
||||
}, {
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
|
|
|
@ -3,11 +3,18 @@
|
|||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Name"
|
||||
model="filter.name"
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Name"
|
||||
model="filter.name">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
|
|
|
@ -3,11 +3,18 @@
|
|||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Client"
|
||||
model="filter.client"
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Client"
|
||||
model="filter.client">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
|
|
|
@ -7,83 +7,4 @@
|
|||
data="$ctrl.logs">
|
||||
</vn-crud-model>
|
||||
|
||||
<vn-vertical>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-title>History</vn-title>
|
||||
<vn-table model="model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="creationDate" default-order="DESC">Date</vn-th>
|
||||
<vn-th field="userFk" class="expendable">Changed by</vn-th>
|
||||
<vn-th field="changedModel" class="expendable">Model</vn-th>
|
||||
<vn-th field="action" class="expendable">Action</vn-th>
|
||||
<vn-th field="changedModelValue" class="expendable">Instance</vn-th>
|
||||
<vn-th>Before</vn-th>
|
||||
<vn-th>After</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="clientLog in $ctrl.logs">
|
||||
<vn-td>
|
||||
{{::clientLog.creationDate | date:'dd/MM/yyyy HH:mm'}}
|
||||
<div class="changes">
|
||||
<div>
|
||||
<span translate class="label">Changed by</span><span class="label">: </span>
|
||||
<span translate class="value">{{::clientLog.user.name}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Model</span><span class="label">: </span>
|
||||
<span translate class="value">{{::clientLog.changedModel}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Action</span><span class="label">: </span>
|
||||
<span translate class="value">{{::clientLog.action}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Instance</span><span class="label">: </span>
|
||||
<span translate class="value">{{::clientLog.changedModelValue}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</vn-td>
|
||||
<vn-td class="expendable">
|
||||
{{::clientLog.user.name}}
|
||||
</vn-td>
|
||||
<vn-td class="expendable">
|
||||
{{::clientLog.changedModel}}
|
||||
</vn-td>
|
||||
<vn-td translate class="expendable">
|
||||
{{::clientLog.action}}
|
||||
</vn-td>
|
||||
<vn-td class="expendable">
|
||||
{{::clientLog.changedModelValue}}
|
||||
</vn-td>
|
||||
<vn-td class="before">
|
||||
<vn-one ng-repeat="old in clientLog.oldProperties">
|
||||
<div>
|
||||
<span translate class="label">{{::old.key}}</span><span class="label">: </span>
|
||||
<span translate class="value">{{::old.value}}</span>
|
||||
</div>
|
||||
</vn-one>
|
||||
</vn-td>
|
||||
<vn-td class="after">
|
||||
<vn-one ng-repeat="new in clientLog.newProperties">
|
||||
<div>
|
||||
<span translate class="label">{{::new.key}}</span><span class="label">: </span>
|
||||
<span translate class="value">{{::new.value}}</span>
|
||||
</div>
|
||||
</vn-one>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
<vn-empty-rows ng-if="model.data.length === 0" translate>
|
||||
No results
|
||||
</vn-empty-rows>
|
||||
</vn-table>
|
||||
</vn-vertical>
|
||||
<vn-pagination
|
||||
model="model"
|
||||
scroll-selector="ui-view">
|
||||
</vn-pagination>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
<vn-log model="model"></vn-log>
|
|
@ -1,5 +1,4 @@
|
|||
import ngModule from '../module';
|
||||
import './style.scss';
|
||||
|
||||
class Controller {
|
||||
constructor($scope, $stateParams) {
|
||||
|
@ -22,18 +21,17 @@ class Controller {
|
|||
set logs(value) {
|
||||
this._logs = value;
|
||||
|
||||
if (this.logs) {
|
||||
this.logs.forEach((log) => {
|
||||
if (this.logs)
|
||||
this.logs.forEach(log => {
|
||||
log.oldProperties = this.getInstance(log.oldInstance);
|
||||
log.newProperties = this.getInstance(log.newInstance);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getInstance(instance) {
|
||||
const properties = [];
|
||||
|
||||
Object.keys(instance).forEach((property) => {
|
||||
Object.keys(instance).forEach(property => {
|
||||
properties.push({key: property, value: instance[property]});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,22 +1,61 @@
|
|||
<div pad-large style="min-width: 30em">
|
||||
<form ng-submit="$ctrl.onSearch()">
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Client id" model="filter.id" vn-focus></vn-textfield>
|
||||
<vn-textfield vn-one label="Tax number" model="filter.fi"></vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Name" model="filter.name"></vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Client id"
|
||||
model="filter.id">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Tax number"
|
||||
model="filter.fi">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Social name" model="filter.socialName"></vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one label="Name"
|
||||
model="filter.name">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Town/City" model="filter.city"></vn-textfield>
|
||||
<vn-textfield vn-one label="Postcode" model="filter.postcode"></vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Social name"
|
||||
model="filter.socialName">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Email" model="filter.email"></vn-textfield>
|
||||
<vn-textfield vn-one label="Phone" model="filter.phone"></vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Town/City"
|
||||
model="filter.city">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Postcode"
|
||||
model="filter.postcode">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Email"
|
||||
model="filter.email">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Phone"
|
||||
model="filter.phone">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal margin-large-top>
|
||||
<vn-submit label="Search"></vn-submit>
|
||||
|
|
|
@ -135,14 +135,14 @@ export default class CrudModel extends ModelProxy {
|
|||
if (!this.isChanged)
|
||||
return null;
|
||||
|
||||
let create = [];
|
||||
let update = [];
|
||||
let remove = [];
|
||||
let deletes = [];
|
||||
let updates = [];
|
||||
let creates = [];
|
||||
|
||||
let pk = this.primaryKey;
|
||||
|
||||
for (let row of this.removed)
|
||||
remove.push(row.$orgRow[pk]);
|
||||
deletes.push(row.$orgRow[pk]);
|
||||
|
||||
for (let row of this._data)
|
||||
if (row.$isNew) {
|
||||
|
@ -150,22 +150,22 @@ export default class CrudModel extends ModelProxy {
|
|||
for (let prop in row)
|
||||
if (prop.charAt(0) !== '$')
|
||||
data[prop] = row[prop];
|
||||
create.push(data);
|
||||
creates.push(data);
|
||||
} else if (row.$oldData) {
|
||||
let data = {};
|
||||
for (let prop in row.$oldData)
|
||||
data[prop] = row[prop];
|
||||
update.push({
|
||||
updates.push({
|
||||
data,
|
||||
where: {[pk]: row.$orgRow[pk]}
|
||||
});
|
||||
}
|
||||
|
||||
let changes = {
|
||||
create: create,
|
||||
update: update,
|
||||
delete: remove
|
||||
};
|
||||
let changes = {deletes, updates, creates};
|
||||
|
||||
for (let prop in changes)
|
||||
if (changes[prop].length === 0)
|
||||
changes[prop] = undefined;
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
|
|
@ -42,3 +42,4 @@ import './chip';
|
|||
import './input-number';
|
||||
import './input-time';
|
||||
import './fetched-tags';
|
||||
import './log';
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
<vn-vertical>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-title>History</vn-title>
|
||||
<vn-table model="$ctrl.model">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="creationDate" default-order="DESC">Date</vn-th>
|
||||
<vn-th field="userFk" class="expendable">Changed by</vn-th>
|
||||
<vn-th field="changedModel" class="expendable">Model</vn-th>
|
||||
<vn-th field="action" class="expendable">Action</vn-th>
|
||||
<vn-th field="changedModelValue" class="expendable">Instance</vn-th>
|
||||
<vn-th>Before</vn-th>
|
||||
<vn-th>After</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<vn-tr ng-repeat="log in $ctrl.model.data">
|
||||
<vn-td>
|
||||
{{::log.creationDate | date:'dd/MM/yyyy HH:mm'}}
|
||||
<div class="changes">
|
||||
<div>
|
||||
<span translate class="label">Changed by</span><span class="label">: </span>
|
||||
<span translate class="value">{{::log.user.name}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Model</span><span class="label">: </span>
|
||||
<span translate class="value">{{::log.changedModel}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Action</span><span class="label">: </span>
|
||||
<span translate class="value">{{::log.action}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Instance</span><span class="label">: </span>
|
||||
<span translate class="value">{{::log.changedModelValue}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</vn-td>
|
||||
<vn-td class="expendable">
|
||||
{{::log.user.name}}
|
||||
</vn-td>
|
||||
<vn-td class="expendable">
|
||||
{{::log.changedModel}}
|
||||
</vn-td>
|
||||
<vn-td translate class="expendable">
|
||||
{{::log.action}}
|
||||
</vn-td>
|
||||
<vn-td class="expendable">
|
||||
{{::log.changedModelValue}}
|
||||
</vn-td>
|
||||
<vn-td class="before">
|
||||
<vn-one ng-repeat="old in log.oldProperties">
|
||||
<div>
|
||||
<span translate class="label">{{::old.key}}</span><span class="label">: </span>
|
||||
<span translate class="value">{{::old.value}}</span>
|
||||
</div>
|
||||
</vn-one>
|
||||
</vn-td>
|
||||
<vn-td class="after">
|
||||
<vn-one ng-repeat="new in log.newProperties">
|
||||
<div>
|
||||
<span translate class="label">{{::new.key}}</span><span class="label">: </span>
|
||||
<span translate class="value">{{::new.value}}</span>
|
||||
</div>
|
||||
</vn-one>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
<vn-empty-rows ng-if="$ctrl.model.data.length === 0" translate>
|
||||
No results
|
||||
</vn-empty-rows>
|
||||
</vn-table>
|
||||
</vn-vertical>
|
||||
<vn-pagination
|
||||
model="$ctrl.model"
|
||||
scroll-selector="ui-view">
|
||||
</vn-pagination>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
|
@ -0,0 +1,9 @@
|
|||
import ngModule from '../../module';
|
||||
import './style.scss';
|
||||
|
||||
ngModule.component('vnLog', {
|
||||
template: require('./index.html'),
|
||||
bindings: {
|
||||
model: '<'
|
||||
}
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
@import 'colors';
|
||||
|
||||
vn-client-log {
|
||||
vn-log {
|
||||
vn-td {
|
||||
vertical-align: initial !important;
|
||||
}
|
|
@ -159,14 +159,13 @@ export default class Controller extends Component {
|
|||
let regex = /((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi;
|
||||
let findPattern = searchString.match(regex);
|
||||
let remnantString = searchString.replace(regex, '').trim();
|
||||
if (findPattern) {
|
||||
if (findPattern)
|
||||
for (let i = 0; i < findPattern.length; i++) {
|
||||
let aux = findPattern[i].split(':');
|
||||
let property = aux[0];
|
||||
let value = aux[1].replace(/\(|\)/g, '');
|
||||
result[property] = value.trim();
|
||||
}
|
||||
}
|
||||
if (remnantString)
|
||||
result.search = remnantString;
|
||||
}
|
||||
|
|
|
@ -13,3 +13,4 @@ Finalize: Finalize
|
|||
Previous: Back
|
||||
Load more: Load more
|
||||
Auto-scroll interrupted, please adjust the search: Auto-scroll interrupted, please adjust the search
|
||||
General search: General search
|
|
@ -24,3 +24,4 @@ Value should be %s characters long: El valor debe ser de %s carácteres de longi
|
|||
Value should have a length between %s and %s: El valor debe tener una longitud de entre %s y %s
|
||||
Value should have at least %s characters: El valor debe tener al menos %s carácteres
|
||||
Value should have at most %s characters: El valor debe tener un máximo de %s carácteres
|
||||
General search: Busqueda general
|
|
@ -4,10 +4,17 @@
|
|||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Id"
|
||||
model="filter.id"
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Id"
|
||||
model="filter.id">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Name"
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
<div pad-large style="min-width: 30em">
|
||||
<form ng-submit="$ctrl.onSearch()">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
|
|
|
@ -21,5 +21,5 @@ window.ngModule = function(moduleName) {
|
|||
});
|
||||
};
|
||||
|
||||
var testsContext = require.context('./', true, /\.spec\.js$/);
|
||||
let testsContext = require.context('./', true, /\.spec\.js$/);
|
||||
testsContext.keys().forEach(testsContext);
|
||||
|
|
|
@ -3,11 +3,18 @@
|
|||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Nickname"
|
||||
model="filter.nickname"
|
||||
label="General search"
|
||||
model="filter.search"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Nickname"
|
||||
model="filter.nickname">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
|
|
|
@ -8,11 +8,6 @@
|
|||
auto-save="true"
|
||||
on-save="$ctrl.onSave()">
|
||||
</vn-crud-model>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="weeklies"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<form name="form">
|
||||
<div margin-medium>
|
||||
<vn-card margin-medium-v pad-medium>
|
||||
|
|
|
@ -2,21 +2,27 @@ import ngModule from '../module';
|
|||
import './style.scss';
|
||||
|
||||
export default class Controller {
|
||||
constructor($scope) {
|
||||
constructor($scope, vnApp, $translate) {
|
||||
this.$scope = $scope;
|
||||
this.vnApp = vnApp;
|
||||
this._ = $translate;
|
||||
|
||||
this.ticketSelected = null;
|
||||
this.filter = {
|
||||
include: [
|
||||
{relation: 'ticket',
|
||||
include: {
|
||||
relation: 'ticket',
|
||||
scope: {
|
||||
fields: ['id', 'clientFk', 'companyFk', 'warehouseFk'],
|
||||
include: [
|
||||
{relation: 'client',
|
||||
{
|
||||
relation: 'client',
|
||||
scope: {
|
||||
fields: ['salesPersonFk', 'name'],
|
||||
include: {
|
||||
relation: 'salesPerson',
|
||||
fields: ['firstName', 'name']
|
||||
scope: {
|
||||
fields: ['id', 'firstName', 'name']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -24,8 +30,8 @@ export default class Controller {
|
|||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.weekdays = [
|
||||
{id: 0, name: 'Monday'},
|
||||
{id: 1, name: 'Tuesday'},
|
||||
|
@ -38,7 +44,7 @@ export default class Controller {
|
|||
}
|
||||
|
||||
onSave() {
|
||||
this.$scope.watcher.notifySaved();
|
||||
this.vnApp.showSuccess(this._.instant('Data saved!'));
|
||||
}
|
||||
|
||||
showClientDescriptor(event, clientFk) {
|
||||
|
@ -65,17 +71,9 @@ export default class Controller {
|
|||
this.expeditionId = expedition.id;
|
||||
this.$scope.deleteWeekly.show();
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.$scope.watcher.check();
|
||||
this.$scope.model.save().then(() => {
|
||||
this.$scope.watcher.notifySaved();
|
||||
this.$scope.model.refresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope'];
|
||||
Controller.$inject = ['$scope', 'vnApp', '$translate'];
|
||||
|
||||
ngModule.component('vnTicketWeekly', {
|
||||
template: require('./index.html'),
|
||||
|
|
|
@ -9,91 +9,81 @@ describe('Client Edit fiscalData path', () => {
|
|||
.waitForLogin('employee');
|
||||
});
|
||||
|
||||
it('should click on the Clients button of the top bar menu', done => {
|
||||
return nightmare
|
||||
it('should click on the Clients button of the top bar menu', async () => {
|
||||
const url = await nightmare
|
||||
.waitToClick(selectors.globalItems.applicationsMenuButton)
|
||||
.wait(selectors.globalItems.applicationsMenuVisible)
|
||||
.waitToClick(selectors.globalItems.clientsButton)
|
||||
.wait(selectors.clientsIndex.createClientButton)
|
||||
.parsedUrl()
|
||||
.then(url => {
|
||||
.parsedUrl();
|
||||
|
||||
expect(url.hash).toEqual('#!/client/index');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it('should search for the user Bruce Banner', done => {
|
||||
return nightmare
|
||||
it('should search for the user Bruce Banner', async () => {
|
||||
const resultCount = await nightmare
|
||||
.wait(selectors.clientsIndex.searchResult)
|
||||
.type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
|
||||
.click(selectors.clientsIndex.searchButton)
|
||||
.waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
|
||||
.countElement(selectors.clientsIndex.searchResult)
|
||||
.then(result => {
|
||||
expect(result).toEqual(1);
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
.countElement(selectors.clientsIndex.searchResult);
|
||||
|
||||
expect(resultCount).toEqual(1);
|
||||
});
|
||||
|
||||
// Confirms all addresses have EQtax false for future propagation test step 1
|
||||
it(`should click on the search result to access to the client's addresses`, () => {
|
||||
return nightmare
|
||||
it(`should click on the search result to access to the client's addresses`, async () => {
|
||||
const url = await nightmare
|
||||
.waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
|
||||
.waitToClick(selectors.clientsIndex.searchResult)
|
||||
.waitToClick(selectors.clientAddresses.addressesButton)
|
||||
.waitForURL('/address/index')
|
||||
.url()
|
||||
.then(url => {
|
||||
.url();
|
||||
|
||||
expect(url).toContain('/address/index');
|
||||
});
|
||||
});
|
||||
|
||||
// Confirms all addresses have EQtax false for future propagation test step 2
|
||||
it(`should click on the 1st edit icon to check EQtax isnt checked`, () => {
|
||||
return nightmare
|
||||
it(`should click on the 1st edit icon to check EQtax isnt checked`, async () => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.clientAddresses.firstEditButton)
|
||||
.wait(selectors.clientAddresses.equalizationTaxCheckboxLabel)
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientAddresses.equalizationTaxCheckboxLabel)
|
||||
.then(value => {
|
||||
expect(value).toBeFalsy();
|
||||
});
|
||||
}, selectors.clientAddresses.equalizationTaxCheckboxLabel);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
// Confirms all addresses have EQtax false for future propagation test step 3
|
||||
it(`should go back to addresses then select the second one and confirm the EQtax isnt checked`, () => {
|
||||
return nightmare
|
||||
it(`should go back to addresses then select the second one and confirm the EQtax isnt checked`, async () => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.clientAddresses.addressesButton)
|
||||
.waitToClick(selectors.clientAddresses.secondEditButton)
|
||||
.wait(selectors.clientAddresses.equalizationTaxCheckboxLabel)
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientAddresses.equalizationTaxCheckboxLabel)
|
||||
.then(value => {
|
||||
expect(value).toBeFalsy();
|
||||
});
|
||||
}, selectors.clientAddresses.equalizationTaxCheckboxLabel);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it(`should click on the fiscal data button`, () => {
|
||||
return nightmare
|
||||
it(`should click on the fiscal data button`, async () => {
|
||||
const url = await nightmare
|
||||
.waitToClick(selectors.clientFiscalData.fiscalDataButton)
|
||||
.waitForURL('fiscal-data')
|
||||
.url()
|
||||
.then(url => {
|
||||
.url();
|
||||
|
||||
expect(url).toContain('fiscal-data');
|
||||
});
|
||||
});
|
||||
|
||||
it('should not be able to edit the verified data checkbox', done => {
|
||||
return nightmare
|
||||
it('should not be able to edit the verified data checkbox', async () => {
|
||||
const result = await nightmare
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).disabled;
|
||||
}, selectors.clientFiscalData.verifiedDataCheckboxInput)
|
||||
.then(value => {
|
||||
expect(value).toBeTruthy();
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
}, selectors.clientFiscalData.verifiedDataCheckboxInput);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -103,46 +93,41 @@ describe('Client Edit fiscalData path', () => {
|
|||
.waitForLogin('administrative');
|
||||
});
|
||||
|
||||
it('should now click on the Clients button of the top bar menu', done => {
|
||||
return nightmare
|
||||
it('should now click on the Clients button of the top bar menu', async () => {
|
||||
const url = await nightmare
|
||||
.waitToClick(selectors.globalItems.applicationsMenuButton)
|
||||
.wait(selectors.globalItems.applicationsMenuVisible)
|
||||
.waitToClick(selectors.globalItems.clientsButton)
|
||||
.wait(selectors.clientsIndex.createClientButton)
|
||||
.parsedUrl()
|
||||
.then(url => {
|
||||
.parsedUrl();
|
||||
|
||||
expect(url.hash).toEqual('#!/client/index');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it('should now search for the user Bruce Banner', done => {
|
||||
return nightmare
|
||||
it('should now search for the user Bruce Banner', async () => {
|
||||
const resultCount = await nightmare
|
||||
.wait(selectors.clientsIndex.searchResult)
|
||||
.type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
|
||||
.click(selectors.clientsIndex.searchButton)
|
||||
.waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
|
||||
.countElement(selectors.clientsIndex.searchResult)
|
||||
.then(result => {
|
||||
expect(result).toEqual(1);
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
.countElement(selectors.clientsIndex.searchResult);
|
||||
|
||||
expect(resultCount).toEqual(1);
|
||||
});
|
||||
|
||||
it(`should access to the client fiscal data`, () => {
|
||||
return nightmare
|
||||
it(`should access to the client fiscal data`, async () => {
|
||||
const url = await nightmare
|
||||
.waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
|
||||
.waitToClick(selectors.clientsIndex.searchResult)
|
||||
.waitToClick(selectors.clientFiscalData.fiscalDataButton)
|
||||
.waitForURL('fiscal-data')
|
||||
.url()
|
||||
.then(url => {
|
||||
.url();
|
||||
|
||||
expect(url).toContain('fiscal-data');
|
||||
});
|
||||
});
|
||||
|
||||
it('should edit the clients fiscal data', done => {
|
||||
return nightmare
|
||||
it('should edit the clients fiscal data', async () => {
|
||||
const result = await nightmare
|
||||
.wait(selectors.clientFiscalData.socialNameInput)
|
||||
.clearInput(selectors.clientFiscalData.socialNameInput)
|
||||
.type(selectors.clientFiscalData.socialNameInput, 'SMASH!')
|
||||
|
@ -168,226 +153,190 @@ describe('Client Edit fiscalData path', () => {
|
|||
.waitToClick(selectors.clientFiscalData.equalizationTaxCheckboxLabel)
|
||||
.waitToClick(selectors.clientFiscalData.verifiedDataCheckboxInput)
|
||||
.click(selectors.clientFiscalData.saveButton)
|
||||
.waitForLastSnackbar()
|
||||
.then(result => {
|
||||
.waitForLastSnackbar();
|
||||
|
||||
expect(result).toEqual('Data saved!');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it('should propagate the Equalization tax', done => {
|
||||
return nightmare
|
||||
it('should propagate the Equalization tax', async () => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.clientFiscalData.acceptPropagationButton)
|
||||
.waitForLastSnackbar()
|
||||
.then(result => {
|
||||
.waitForLastSnackbar();
|
||||
|
||||
expect(result).toEqual('Equivalent tax spreaded');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
// confirm all addresses have now EQtax checked step 1
|
||||
it(`should click on the addresses button to access to the client's addresses`, () => {
|
||||
return nightmare
|
||||
it(`should click on the addresses button to access to the client's addresses`, async () => {
|
||||
const url = await nightmare
|
||||
.waitToClick(selectors.clientAddresses.addressesButton)
|
||||
.waitForURL('/address/index')
|
||||
.url()
|
||||
.then(url => {
|
||||
.url();
|
||||
|
||||
expect(url).toContain('/address/index');
|
||||
});
|
||||
});
|
||||
|
||||
// confirm all addresses have now EQtax checked step 2
|
||||
it(`should click on the 1st edit icon to confirm EQtax is checked`, () => {
|
||||
return nightmare
|
||||
it(`should click on the 1st edit icon to confirm EQtax is checked`, async () => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.clientAddresses.firstEditButton)
|
||||
.wait(selectors.clientAddresses.equalizationTaxCheckboxLabel)
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientAddresses.equalizationTaxCheckboxLabel)
|
||||
.then(value => {
|
||||
expect(value).toBeTruthy();
|
||||
});
|
||||
}, selectors.clientAddresses.equalizationTaxCheckboxLabel);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
// confirm all addresses have now EQtax checked step 3
|
||||
it(`should go back to addresses then select the second one and confirm the EQtax is checked`, () => {
|
||||
return nightmare
|
||||
it(`should go back to addresses then select the second one and confirm the EQtax is checked`, async () => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.clientAddresses.addressesButton)
|
||||
.waitToClick(selectors.clientAddresses.secondEditButton)
|
||||
.wait(selectors.clientAddresses.equalizationTaxCheckboxLabel)
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientAddresses.equalizationTaxCheckboxLabel)
|
||||
.then(value => {
|
||||
expect(value).toBeTruthy();
|
||||
});
|
||||
}, selectors.clientAddresses.equalizationTaxCheckboxLabel);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should navigate back to fiscal data to confirm its name have been edited', done => {
|
||||
return nightmare
|
||||
it('should navigate back to fiscal data to confirm its name have been edited', async () => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.clientFiscalData.fiscalDataButton)
|
||||
.wait(selectors.clientFiscalData.socialNameInput)
|
||||
.getInputValue(selectors.clientFiscalData.socialNameInput)
|
||||
.then(result => {
|
||||
.getInputValue(selectors.clientFiscalData.socialNameInput);
|
||||
|
||||
expect(result).toEqual('SMASH!');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it('should confirm the fiscal id have been edited', done => {
|
||||
return nightmare
|
||||
.getInputValue(selectors.clientFiscalData.fiscalIdInput)
|
||||
.then(result => {
|
||||
it('should confirm the fiscal id have been edited', async () => {
|
||||
const result = await nightmare
|
||||
.getInputValue(selectors.clientFiscalData.fiscalIdInput);
|
||||
|
||||
expect(result).toEqual('94980061C');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it('should confirm the address have been edited', done => {
|
||||
return nightmare
|
||||
.getInputValue(selectors.clientFiscalData.addressInput)
|
||||
.then(result => {
|
||||
it('should confirm the address have been edited', async () => {
|
||||
const result = await nightmare
|
||||
.getInputValue(selectors.clientFiscalData.addressInput);
|
||||
|
||||
expect(result).toEqual('Somewhere edited');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it('should confirm the postcode have been edited', done => {
|
||||
return nightmare
|
||||
.getInputValue(selectors.clientFiscalData.postcodeInput)
|
||||
.then(result => {
|
||||
it('should confirm the postcode have been edited', async () => {
|
||||
const result = await nightmare
|
||||
.getInputValue(selectors.clientFiscalData.postcodeInput);
|
||||
|
||||
expect(result).toEqual('12345');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it('should confirm the city have been edited', done => {
|
||||
return nightmare
|
||||
.getInputValue(selectors.clientFiscalData.cityInput)
|
||||
.then(result => {
|
||||
it('should confirm the city have been edited', async () => {
|
||||
const result = await nightmare
|
||||
.getInputValue(selectors.clientFiscalData.cityInput);
|
||||
|
||||
expect(result).toEqual('N/A');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it(`should confirm the country have been selected`, () => {
|
||||
return nightmare
|
||||
.getInputValue(selectors.clientFiscalData.countryInput)
|
||||
.then(result => {
|
||||
it(`should confirm the country have been selected`, async () => {
|
||||
const result = await nightmare
|
||||
.getInputValue(selectors.clientFiscalData.countryInput);
|
||||
|
||||
expect(result).toEqual('Francia');
|
||||
});
|
||||
});
|
||||
|
||||
it(`should confirm the province have been selected`, () => {
|
||||
return nightmare
|
||||
.getInputValue(selectors.clientFiscalData.provinceInput)
|
||||
.then(result => {
|
||||
it(`should confirm the province have been selected`, async () => {
|
||||
const result = await nightmare
|
||||
.getInputValue(selectors.clientFiscalData.provinceInput);
|
||||
|
||||
expect(result).toEqual('Province two');
|
||||
});
|
||||
});
|
||||
|
||||
it('should confirm active checkbox is unchecked', done => {
|
||||
return nightmare
|
||||
it('should confirm active checkbox is unchecked', async () => {
|
||||
const result = await nightmare
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientFiscalData.activeCheckboxLabel)
|
||||
.then(value => {
|
||||
expect(value).toBeFalsy();
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
}, selectors.clientFiscalData.activeCheckboxLabel);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should confirm frozen checkbox is unchecked', done => {
|
||||
return nightmare
|
||||
it('should confirm frozen checkbox is unchecked', async () => {
|
||||
const result = await nightmare
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientFiscalData.frozenCheckboxLabel)
|
||||
.then(value => {
|
||||
expect(value).toBeFalsy();
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
}, selectors.clientFiscalData.frozenCheckboxLabel);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should confirm Has to invoice checkbox is unchecked', done => {
|
||||
return nightmare
|
||||
it('should confirm Has to invoice checkbox is unchecked', async () => {
|
||||
const result = await nightmare
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientFiscalData.hasToInvoiceCheckboxLabel)
|
||||
.then(value => {
|
||||
expect(value).toBeFalsy();
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
}, selectors.clientFiscalData.hasToInvoiceCheckboxLabel);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should confirm Vies checkbox is checked', done => {
|
||||
return nightmare
|
||||
it('should confirm Vies checkbox is checked', async () => {
|
||||
const result = await nightmare
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientFiscalData.viesCheckboxInput)
|
||||
.then(value => {
|
||||
expect(value).toBeTruthy();
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
}, selectors.clientFiscalData.viesCheckboxInput);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should confirm Invoice by mail checkbox is unchecked', done => {
|
||||
return nightmare
|
||||
it('should confirm Invoice by mail checkbox is unchecked', async () => {
|
||||
const result = await nightmare
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientFiscalData.invoiceByMailCheckboxLabel)
|
||||
.then(value => {
|
||||
expect(value).toBeFalsy();
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
}, selectors.clientFiscalData.invoiceByMailCheckboxLabel);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should confirm invoice by address checkbox is unchecked', done => {
|
||||
return nightmare
|
||||
it('should confirm invoice by address checkbox is unchecked', async () => {
|
||||
const result = await nightmare
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientFiscalData.invoiceByAddressCheckboxInput)
|
||||
.then(value => {
|
||||
expect(value).toBeFalsy();
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
}, selectors.clientFiscalData.invoiceByAddressCheckboxInput);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should confirm Equalization tax checkbox is checked', done => {
|
||||
return nightmare
|
||||
it('should confirm Equalization tax checkbox is checked', async () => {
|
||||
const result = await nightmare
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientFiscalData.equalizationTaxCheckboxLabel)
|
||||
.then(value => {
|
||||
expect(value).toBeTruthy();
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
}, selectors.clientFiscalData.equalizationTaxCheckboxLabel);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should confirm Verified data checkbox is checked', done => {
|
||||
return nightmare
|
||||
it('should confirm Verified data checkbox is checked', async () => {
|
||||
const result = await nightmare
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientFiscalData.verifiedDataCheckboxInput)
|
||||
.then(value => {
|
||||
expect(value).toBeTruthy();
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
}, selectors.clientFiscalData.verifiedDataCheckboxInput);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
|
||||
// confirm invoice by address checkbox gets checked if the EQtax differs between addresses step 1
|
||||
it(`should click on the addresses button to access to the client's addresses`, () => {
|
||||
return nightmare
|
||||
it(`should click on the addresses button to access to the client's addresses`, async () => {
|
||||
const url = await nightmare
|
||||
.waitToClick(selectors.clientAddresses.addressesButton)
|
||||
.waitForURL('/address/index')
|
||||
.url()
|
||||
.then(url => {
|
||||
.url();
|
||||
|
||||
expect(url).toContain('/address/index');
|
||||
});
|
||||
});
|
||||
|
||||
// confirm invoice by address checkbox gets checked if the EQtax differs between addresses step 2
|
||||
it(`should click on the 1st edit icon to access the address details and uncheck EQtax checkbox`, () => {
|
||||
return nightmare
|
||||
it(`should click on the 1st edit icon to access the address details and uncheck EQtax checkbox`, async () => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.clientAddresses.firstEditButton)
|
||||
.waitToClick(selectors.clientAddresses.equalizationTaxCheckboxLabel)
|
||||
.click(selectors.clientAddresses.saveButton)
|
||||
|
@ -398,17 +347,15 @@ describe('Client Edit fiscalData path', () => {
|
|||
});
|
||||
|
||||
// confirm invoice by address checkbox gets checked if the EQtax differs between addresses step 3
|
||||
it('should navigate back to fiscal data to confirm invoice by address is now checked', done => {
|
||||
return nightmare
|
||||
it('should navigate back to fiscal data to confirm invoice by address is now checked', async () => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.clientFiscalData.fiscalDataButton)
|
||||
.wait(selectors.clientFiscalData.invoiceByAddressCheckboxInput)
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).checked;
|
||||
}, selectors.clientFiscalData.invoiceByAddressCheckboxInput)
|
||||
.then(value => {
|
||||
expect(value).toBeTruthy();
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
}, selectors.clientFiscalData.invoiceByAddressCheckboxInput);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import createNightmare from '../../helpers/nightmare';
|
||||
|
||||
describe('Item', () => {
|
||||
describe('Summary path', () => {
|
||||
describe('Item summary path', () => {
|
||||
const nightmare = createNightmare();
|
||||
|
||||
beforeAll(() => {
|
||||
|
@ -34,7 +33,7 @@ describe('Item', () => {
|
|||
const result = await nightmare
|
||||
.waitForTextInElement(selectors.itemsIndex.searchResult, 'Gem of Time')
|
||||
.isVisible(selectors.itemSummary.basicData)
|
||||
.then((result) => {
|
||||
.then(result => {
|
||||
expect(result).toBeFalsy();
|
||||
return nightmare
|
||||
.waitToClick(selectors.itemsIndex.searchResultPreviewButton)
|
||||
|
@ -108,7 +107,7 @@ describe('Item', () => {
|
|||
const result = await nightmare
|
||||
.waitForTextInElement(selectors.itemsIndex.searchResult, 'Gem of Mind')
|
||||
.isVisible(selectors.itemSummary.basicData)
|
||||
.then((result) => {
|
||||
.then(result => {
|
||||
expect(result).toBeFalsy();
|
||||
return nightmare
|
||||
.waitToClick(selectors.itemsIndex.searchResultPreviewButton)
|
||||
|
@ -211,4 +210,3 @@ describe('Item', () => {
|
|||
expect(result).toContain('4');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import createNightmare from '../../helpers/nightmare';
|
||||
|
||||
describe('Item', () => {
|
||||
describe('Edit tax path', () => {
|
||||
describe('Item edit tax path', () => {
|
||||
const nightmare = createNightmare();
|
||||
|
||||
beforeAll(() => {
|
||||
|
@ -81,4 +80,3 @@ describe('Item', () => {
|
|||
expect(thirdVatType).toEqual('Reduced VAT');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import createNightmare from '../../helpers/nightmare';
|
||||
|
||||
describe('Item', () => {
|
||||
describe('Create tags path', () => {
|
||||
describe('Item create tags path', () => {
|
||||
const nightmare = createNightmare();
|
||||
|
||||
beforeAll(() => {
|
||||
|
@ -10,45 +9,39 @@ describe('Item', () => {
|
|||
.waitForLogin('buyer');
|
||||
});
|
||||
|
||||
it('should access to the items index by clicking the items button', done => {
|
||||
return nightmare
|
||||
it('should access to the items index by clicking the items button', async () => {
|
||||
const url = await nightmare
|
||||
.click(selectors.moduleAccessView.itemsSectionButton)
|
||||
.wait(selectors.itemsIndex.createItemButton)
|
||||
.parsedUrl()
|
||||
.then(url => {
|
||||
.parsedUrl();
|
||||
|
||||
expect(url.hash).toEqual('#!/item/index');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it('should search for the item Gem of Time', done => {
|
||||
return nightmare
|
||||
it('should search for the item Gem of Time', async () => {
|
||||
const resultCount = await nightmare
|
||||
.wait(selectors.itemsIndex.searchResult)
|
||||
.type(selectors.itemsIndex.searchItemInput, 'Gem of Time')
|
||||
.click(selectors.itemsIndex.searchButton)
|
||||
.waitForNumberOfElements(selectors.itemsIndex.searchResult, 1)
|
||||
.countElement(selectors.itemsIndex.searchResult)
|
||||
.then(result => {
|
||||
expect(result).toEqual(1);
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
.countElement(selectors.itemsIndex.searchResult);
|
||||
|
||||
expect(resultCount).toEqual(1);
|
||||
});
|
||||
|
||||
it(`should click on the search result to access to the item tags`, done => {
|
||||
return nightmare
|
||||
it(`should click on the search result to access to the item tags`, async () => {
|
||||
const url = await nightmare
|
||||
.waitForTextInElement(selectors.itemsIndex.searchResult, 'Gem of Time')
|
||||
.waitToClick(selectors.itemsIndex.searchResult)
|
||||
.waitToClick(selectors.itemTags.tagsButton)
|
||||
.waitForURL('tags')
|
||||
.url()
|
||||
.then(url => {
|
||||
.url();
|
||||
|
||||
expect(url).toContain('tags');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it(`should create a new tag and delete a former one`, done => {
|
||||
return nightmare
|
||||
it(`should create a new tag and delete a former one`, async () => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.itemTags.firstRemoveTagButton)
|
||||
.waitToClick(selectors.itemTags.addItemTagButton)
|
||||
.waitToClick(selectors.itemTags.seventhTagSelect)
|
||||
|
@ -57,29 +50,26 @@ describe('Item', () => {
|
|||
.clearInput(selectors.itemTags.seventhRelevancyInput)
|
||||
.type(selectors.itemTags.seventhRelevancyInput, '1')
|
||||
.click(selectors.itemTags.submitItemTagsButton)
|
||||
.waitForLastSnackbar()
|
||||
.then(result => {
|
||||
expect(result).toEqual('Data saved!');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
.waitForLastSnackbar();
|
||||
|
||||
it(`should reload tags form to check that the changes are saved`, () => {
|
||||
return nightmare
|
||||
.click(selectors.itemBasicData.basicDataButton)
|
||||
.wait(selectors.itemBasicData.nameInput)
|
||||
.click(selectors.itemTags.tagsButton)
|
||||
.wait('vn-item-tags');
|
||||
expect(result).toEqual('Data saved!');
|
||||
});
|
||||
|
||||
it(`should confirm the first row data is the expected one`, async () => {
|
||||
let tag = await nightmare.getProperty(selectors.itemTags.firstTagSelect, 'value');
|
||||
let value = await nightmare.getProperty(selectors.itemTags.firstValueInput, 'value');
|
||||
let relevancy = await nightmare.getProperty(selectors.itemTags.firstRelevancyInput, 'value');
|
||||
let result = await nightmare
|
||||
.click(selectors.itemBasicData.basicDataButton)
|
||||
.wait(selectors.itemBasicData.nameInput)
|
||||
.click(selectors.itemTags.tagsButton)
|
||||
.wait('vn-item-tags')
|
||||
.getProperty(selectors.itemTags.firstTagSelect, 'value');
|
||||
|
||||
expect(tag).toEqual('Ancho de la base');
|
||||
expect(value).toEqual('50');
|
||||
expect(relevancy).toEqual('1');
|
||||
expect(result).toEqual('Ancho de la base');
|
||||
result = await nightmare.getProperty(selectors.itemTags.firstValueInput, 'value');
|
||||
|
||||
expect(result).toEqual('50');
|
||||
result = await nightmare.getProperty(selectors.itemTags.firstRelevancyInput, 'value');
|
||||
|
||||
expect(result).toEqual('1');
|
||||
});
|
||||
|
||||
it(`should confirm the second row data is the expected one`, async () => {
|
||||
|
@ -92,7 +82,7 @@ describe('Item', () => {
|
|||
expect(relevancy).toEqual('2');
|
||||
});
|
||||
|
||||
it(`should confirm the second row data is the expected one`, async() => {
|
||||
it(`should confirm the third row data is the expected one`, async () => {
|
||||
let tag = await nightmare.getProperty(selectors.itemTags.thirdTagSelect, 'value');
|
||||
let value = await nightmare.getProperty(selectors.itemTags.thirdValueInput, 'value');
|
||||
let relevancy = await nightmare.getProperty(selectors.itemTags.thirdRelevancyInput, 'value');
|
||||
|
@ -122,4 +112,3 @@ describe('Item', () => {
|
|||
expect(relevancy).toEqual('5');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import createNightmare from '../../helpers/nightmare';
|
||||
|
||||
describe('Item', () => {
|
||||
describe('Create niche path', () => {
|
||||
describe('Item create niche path', () => {
|
||||
const nightmare = createNightmare();
|
||||
|
||||
beforeAll(() => {
|
||||
|
@ -10,102 +9,85 @@ describe('Item', () => {
|
|||
.waitForLogin('buyer');
|
||||
});
|
||||
|
||||
it('should access to the items index by clicking the items button', done => {
|
||||
return nightmare
|
||||
it('should access to the items index by clicking the items button', async () => {
|
||||
const url = await nightmare
|
||||
.click(selectors.moduleAccessView.itemsSectionButton)
|
||||
.wait(selectors.itemsIndex.createItemButton)
|
||||
.parsedUrl()
|
||||
.then(url => {
|
||||
.parsedUrl();
|
||||
|
||||
expect(url.hash).toEqual('#!/item/index');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it('should search for the item Gem of Time', done => {
|
||||
return nightmare
|
||||
it('should search for the item Gem of Time', async () => {
|
||||
const resultCount = await nightmare
|
||||
.wait(selectors.itemsIndex.searchResult)
|
||||
.type(selectors.itemsIndex.searchItemInput, 'Gem of Time')
|
||||
.click(selectors.itemsIndex.searchButton)
|
||||
.waitForNumberOfElements(selectors.itemsIndex.searchResult, 1)
|
||||
.countElement(selectors.itemsIndex.searchResult)
|
||||
.then(result => {
|
||||
expect(result).toEqual(1);
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
.countElement(selectors.itemsIndex.searchResult);
|
||||
|
||||
expect(resultCount).toEqual(1);
|
||||
});
|
||||
|
||||
it(`should click on the search result to access to the item niches`, done => {
|
||||
return nightmare
|
||||
it(`should click on the search result to access to the item niches`, async () => {
|
||||
const url = await nightmare
|
||||
.waitForTextInElement(selectors.itemsIndex.searchResult, 'Gem of Time')
|
||||
.waitToClick(selectors.itemsIndex.searchResult)
|
||||
.waitToClick(selectors.itemNiches.nicheButton)
|
||||
.waitForURL('niche')
|
||||
.url()
|
||||
.then(url => {
|
||||
.url();
|
||||
|
||||
expect(url).toContain('niche');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it(`should click create a new niche and delete a former one`, done => {
|
||||
return nightmare
|
||||
it(`should click create a new niche and delete a former one`, async () => {
|
||||
const result = await nightmare
|
||||
.waitToClick(selectors.itemNiches.addNicheButton)
|
||||
.waitToClick(selectors.itemNiches.secondNicheRemoveButton)
|
||||
.waitToClick(selectors.itemNiches.thirdWarehouseSelect)
|
||||
.waitToClick(selectors.itemNiches.thirdWarehouseSelectFourthOption)
|
||||
.type(selectors.itemNiches.thirdCodeInput, 'A4')
|
||||
.click(selectors.itemNiches.submitNichesButton)
|
||||
.waitForLastSnackbar()
|
||||
.then(result => {
|
||||
.waitForLastSnackbar();
|
||||
|
||||
expect(result).toEqual('Data saved!');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it(`should confirm the first niche is the expected one`, done => {
|
||||
return nightmare
|
||||
it(`should confirm the first niche is the expected one`, async () => {
|
||||
let result = await nightmare
|
||||
.click(selectors.itemBasicData.basicDataButton)
|
||||
.wait(selectors.itemBasicData.nameInput)
|
||||
.click(selectors.itemNiches.nicheButton)
|
||||
.waitForTextInInput(selectors.itemNiches.firstWarehouseSelect, 'Warehouse One')
|
||||
.getInputValue(selectors.itemNiches.firstWarehouseSelect)
|
||||
.then(result => {
|
||||
.getInputValue(selectors.itemNiches.firstWarehouseSelect);
|
||||
|
||||
expect(result).toEqual('Warehouse One');
|
||||
return nightmare
|
||||
result = await nightmare
|
||||
.getInputValue(selectors.itemNiches.firstCodeInput);
|
||||
})
|
||||
.then(result => {
|
||||
|
||||
expect(result).toEqual('A1');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it(`should confirm the second niche is the expected one`, done => {
|
||||
return nightmare
|
||||
.getInputValue(selectors.itemNiches.secondWarehouseSelect)
|
||||
.then(result => {
|
||||
it(`should confirm the second niche is the expected one`, async () => {
|
||||
let result = await nightmare
|
||||
.getInputValue(selectors.itemNiches.secondWarehouseSelect);
|
||||
|
||||
expect(result).toEqual('Warehouse Three');
|
||||
return nightmare
|
||||
result = await nightmare
|
||||
.getInputValue(selectors.itemNiches.secondCodeInput);
|
||||
})
|
||||
.then(result => {
|
||||
|
||||
|
||||
expect(result).toEqual('A3');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
|
||||
it(`should confirm the third niche is the expected one`, done => {
|
||||
return nightmare
|
||||
.getInputValue(selectors.itemNiches.thirdWarehouseSelect)
|
||||
.then(result => {
|
||||
it(`should confirm the third niche is the expected one`, async () => {
|
||||
let result = await nightmare
|
||||
.getInputValue(selectors.itemNiches.thirdWarehouseSelect);
|
||||
|
||||
expect(result).toEqual('Warehouse Two');
|
||||
return nightmare
|
||||
result = await nightmare
|
||||
.getInputValue(selectors.itemNiches.thirdCodeInput);
|
||||
})
|
||||
.then(result => {
|
||||
|
||||
expect(result).toEqual('A4');
|
||||
done();
|
||||
}).catch(done.fail);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -38,7 +38,7 @@ let defaultPort = proxyConf.defaultPort;
|
|||
// Development
|
||||
|
||||
gulp.task('default', () => {
|
||||
return gulp.start('environment', 'services', 'client');
|
||||
return gulp.start('services', 'client');
|
||||
});
|
||||
|
||||
gulp.task('environment', async () => {
|
||||
|
@ -55,13 +55,13 @@ gulp.task('client', ['build-clean'], async () => {
|
|||
* Starts all backend services, including the nginx proxy and the database.
|
||||
*/
|
||||
gulp.task('services', async () => {
|
||||
await runSequenceP('environment', 'docker-start', 'services-only', 'nginx');
|
||||
await runSequenceP('docker-start', 'services-only', 'nginx');
|
||||
});
|
||||
|
||||
/**
|
||||
* Starts backend services.
|
||||
*/
|
||||
gulp.task('services-only', async () => {
|
||||
gulp.task('services-only', ['environment'], async () => {
|
||||
const services = await getServices();
|
||||
for (let service of services)
|
||||
require(service.index).start(service.port);
|
||||
|
@ -354,10 +354,9 @@ gulp.task('webpack-dev-server', function() {
|
|||
const webpackConfig = require('./webpack.config.js');
|
||||
let configCopy = Object.create(webpackConfig);
|
||||
|
||||
for (let entry in configCopy.entry) {
|
||||
for (let entry in configCopy.entry)
|
||||
configCopy.entry[entry]
|
||||
.unshift(`webpack-dev-server/client?http://127.0.0.1:${devServerPort}/`);
|
||||
}
|
||||
|
||||
let compiler = webpack(configCopy);
|
||||
new WebpackDevServer(compiler, {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -64,7 +64,7 @@
|
|||
"mysql2": "^1.6.1",
|
||||
"nightmare": "^3.0.1",
|
||||
"node-sass": "^4.9.3",
|
||||
"nodemon": "^1.18.4",
|
||||
"nodemon": "^1.18.5",
|
||||
"plugin-error": "^1.0.1",
|
||||
"raw-loader": "*",
|
||||
"run-sequence": "^2.2.1",
|
||||
|
@ -79,6 +79,6 @@
|
|||
"test": "nodemon -q services_tests.js -w services",
|
||||
"dbtest": "nodemon -q db_tests.js -w services/db/tests",
|
||||
"lint": "eslint ./ --cache --ignore-pattern .gitignore",
|
||||
"services": "node --inspect ./node_modules/gulp/bin/gulp.js services"
|
||||
"services": "nodemon --inspect -w services ./node_modules/gulp/bin/gulp.js services"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -325,19 +325,19 @@ INSERT INTO `vn`.`bankEntity`(`id`, `countryFk`, `name`, `bic`)
|
|||
|
||||
INSERT INTO `vn`.`company`(`id`, `code`, `supplierAccountFk`, `workerManagerFk`, `companyCode`, `sage200Company`)
|
||||
VALUES
|
||||
( 69 , 'CCs', NULL, 30, NULL, 1),
|
||||
( 442 , 'VNL', 241, 30, 2 , 2),
|
||||
( 567 , 'VNH', NULL, 30, NULL, 3),
|
||||
( 791 , 'FTH', NULL, 30, NULL, 4),
|
||||
( 1381, 'ORN', NULL, 30, NULL, 5);
|
||||
( 69 , 'CCs', NULL, 30, NULL, 0),
|
||||
( 442 , 'VNL', 241, 30, 2 , 1),
|
||||
( 567 , 'VNH', NULL, 30, NULL, 4),
|
||||
( 791 , 'FTH', NULL, 30, NULL, 3),
|
||||
( 1381, 'ORN', NULL, 30, NULL, 7);
|
||||
|
||||
INSERT INTO `vn`.`invoiceOut`(`id`,`ref`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `pdf`)
|
||||
VALUES
|
||||
( 1, 'T1111111' , 'T', 500 , DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 101, CURDATE(), 442, CURDATE(), CURDATE(), 1, 1),
|
||||
( 2, 'V2222222' , 'V', 350.50 , DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 102, CURDATE(), 442, CURDATE(), CURDATE(), 1, 1),
|
||||
( 3, 'E3333333' , 'E', 90.30 , CURDATE(), 103, CURDATE(), 442, CURDATE(), CURDATE(), 1, 1),
|
||||
( 4, 'E4444444' , 'E', 290.30 , DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 103, CURDATE(), 442, CURDATE(), CURDATE(), 1, 1),
|
||||
( 5, 'E5555555' , 'E', 190.30 , DATE_ADD(CURDATE(), INTERVAL +2 MONTH), 103, CURDATE(), 442, CURDATE(), CURDATE(), 1, 1);
|
||||
( 1, '1', 'T', 500 , DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 101, CURDATE(), 442, CURDATE(), CURDATE(), 1, 1),
|
||||
( 2, '1', 'V', 350.50 , DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 102, CURDATE(), 442, CURDATE(), CURDATE(), 1, 1),
|
||||
( 3, '1', 'E', 90.30 , CURDATE(), 103, CURDATE(), 442, CURDATE(), CURDATE(), 1, 1),
|
||||
( 4, '1', 'E', 290.30 , DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 103, CURDATE(), 442, CURDATE(), CURDATE(), 1, 1),
|
||||
( 5, '1', 'R', 190.30 , DATE_ADD(CURDATE(), INTERVAL +2 MONTH), 103, CURDATE(), 442, CURDATE(), CURDATE(), 1, 1);
|
||||
|
||||
INSERT INTO `vn`.`ticket`(`id`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `created`)
|
||||
VALUES
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
module.exports = State => {
|
||||
var serverFilter = {where: {order: {gt: 0}}, order: 'order, name'};
|
||||
State.defineScope(serverFilter);
|
||||
};
|
|
@ -1,58 +0,0 @@
|
|||
module.exports = Self => {
|
||||
/**
|
||||
* Catches database errors overriding
|
||||
* model.create() and model.upsert() methods
|
||||
* @param {Object} replaceErrFunc - Callback
|
||||
*/
|
||||
Self.rewriteDbError = function(replaceErrFunc) {
|
||||
this.once('attached', () => {
|
||||
let realUpsert = this.upsert;
|
||||
this.upsert = async(data, options, cb) => {
|
||||
if (options instanceof Function) {
|
||||
cb = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
try {
|
||||
await realUpsert.call(this, data, options);
|
||||
if (cb) cb();
|
||||
} catch (err) {
|
||||
let myErr = replaceErr(err, replaceErrFunc);
|
||||
if (cb)
|
||||
cb(myErr);
|
||||
else
|
||||
throw myErr;
|
||||
}
|
||||
};
|
||||
|
||||
let realCreate = this.create;
|
||||
this.create = async(data, options, cb) => {
|
||||
if (options instanceof Function) {
|
||||
cb = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
try {
|
||||
await realCreate.call(this, data, options);
|
||||
if (cb) cb();
|
||||
} catch (err) {
|
||||
let myErr = replaceErr(err, replaceErrFunc);
|
||||
if (cb)
|
||||
cb(myErr);
|
||||
else
|
||||
throw myErr;
|
||||
}
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
function replaceErr(err, replaceErrFunc) {
|
||||
if (Array.isArray(err)) {
|
||||
let errs = [];
|
||||
for (let e of err)
|
||||
errs.push(replaceErrFunc(e));
|
||||
return errs;
|
||||
}
|
||||
return replaceErrFunc(err);
|
||||
}
|
||||
};
|
|
@ -10,11 +10,9 @@ describe('Model crud()', () => {
|
|||
|
||||
it('should create a new instance', async () => {
|
||||
let data = {code: '500', itemFk: '1'};
|
||||
let creates = [data];
|
||||
|
||||
crudObject = {
|
||||
create: [data]
|
||||
};
|
||||
await ItemBarcode.crud(crudObject);
|
||||
await ItemBarcode.crud(null, null, creates);
|
||||
let instance = await ItemBarcode.findOne({where: data});
|
||||
insertId = instance.id;
|
||||
|
||||
|
@ -23,23 +21,20 @@ describe('Model crud()', () => {
|
|||
});
|
||||
|
||||
it('should update the instance', async () => {
|
||||
crudObject = {
|
||||
update: [{
|
||||
let updates = [{
|
||||
where: {id: insertId},
|
||||
data: {code: '501', itemFk: 1}
|
||||
}]
|
||||
};
|
||||
await ItemBarcode.crud(crudObject);
|
||||
}];
|
||||
|
||||
await ItemBarcode.crud(null, updates);
|
||||
let instance = await ItemBarcode.findById(insertId);
|
||||
|
||||
expect(instance.code).toEqual('501');
|
||||
});
|
||||
|
||||
it('should delete the created instance', async () => {
|
||||
crudObject = {
|
||||
delete: [insertId]
|
||||
};
|
||||
await ItemBarcode.crud(crudObject);
|
||||
let deletes = [insertId];
|
||||
await ItemBarcode.crud(deletes);
|
||||
let instance = await ItemBarcode.findById(insertId);
|
||||
|
||||
expect(instance).toEqual(null);
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
module.exports = function(Self) {
|
||||
Self.validateBinded = function(propertyName, validatorFn, options) {
|
||||
var customValidator = function(err) {
|
||||
if (!validatorFn(this[propertyName])) err();
|
||||
};
|
||||
options.isExportable = true;
|
||||
options.bindedFunction = validatorFn;
|
||||
this.validate(propertyName, customValidator, options);
|
||||
};
|
||||
};
|
|
@ -1,5 +1,4 @@
|
|||
module.exports = Self => {
|
||||
Self.defineScope({where: {isManaged: {neq: 0}}});
|
||||
require('../methods/agency/landsThatDay')(Self);
|
||||
require('../methods/agency/getFirstShipped')(Self);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/state/list')(Self);
|
||||
|
||||
/**
|
||||
* Checks if the alertLevel of a state is 0.
|
||||
*
|
||||
|
|
|
@ -5,11 +5,10 @@ const UserError = require('../helpers').UserError;
|
|||
module.exports = function(Self) {
|
||||
Self.ParameterizedSQL = ParameterizedSQL;
|
||||
|
||||
require('../methods/vn-model/validateBinded')(Self);
|
||||
require('../methods/vn-model/rewriteDbError')(Self);
|
||||
require('../methods/vn-model/getSetValues')(Self);
|
||||
|
||||
Self.setup = function() {
|
||||
Object.assign(Self, {
|
||||
setup() {
|
||||
Self.super_.setup.call(this);
|
||||
|
||||
// Register field ACL validation
|
||||
|
@ -21,149 +20,190 @@ module.exports = function(Self) {
|
|||
this.beforeRemote('replaceOrCreate', ctx => this.checkInsertAcls(ctx));
|
||||
|
||||
this.remoteMethod('crud', {
|
||||
description: 'Create, update or/and delete instances from model with a single request',
|
||||
description: `Create, update or/and delete instances from model with a single request`,
|
||||
accessType: 'WRITE',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'actions',
|
||||
type: 'Object',
|
||||
require: true,
|
||||
description: 'Instances to update, example: {create: [instances], update: [instances], delete: [ids]}',
|
||||
http: {source: 'body'}
|
||||
}
|
||||
],
|
||||
http: {
|
||||
path: `/crud`,
|
||||
verb: 'POST'
|
||||
arg: 'deletes',
|
||||
description: `Identifiers of instances to delete`,
|
||||
type: ['Integer']
|
||||
}, {
|
||||
arg: 'updates',
|
||||
description: `Instances to update with it's identifier {where, data}`,
|
||||
type: ['Object']
|
||||
}, {
|
||||
arg: 'creates',
|
||||
description: `Instances to create`,
|
||||
type: ['Object']
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
Self.defineScope = function(serverFilter) {
|
||||
this.remoteMethodCtx('list', {
|
||||
accepts: [
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
description: 'Filter defining where'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: [this.modelName],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
verb: 'get',
|
||||
path: '/list'
|
||||
}
|
||||
});
|
||||
|
||||
this.list = function(ctx, clientFilter, cb) {
|
||||
let clientFields = (clientFilter && clientFilter.fields) ? clientFilter.fields : [];
|
||||
let serverFields = (serverFilter && serverFilter.fields) ? serverFilter.fields : [];
|
||||
let fields = clientFields.filter(itemC => {
|
||||
return serverFields.some(itemS => itemS === itemC);
|
||||
});
|
||||
let and = [];
|
||||
let order;
|
||||
let limit;
|
||||
let filter = {order: order, limit: limit};
|
||||
|
||||
if (clientFilter && clientFilter.where)
|
||||
and.push(clientFilter.where);
|
||||
if (serverFilter && serverFilter.where)
|
||||
and.push(serverFilter.where);
|
||||
|
||||
if (clientFilter && clientFilter.order)
|
||||
order = clientFilter.order;
|
||||
else if (serverFilter && serverFilter.order)
|
||||
order = serverFilter.order;
|
||||
|
||||
if (serverFilter && serverFilter.limit)
|
||||
limit = serverFilter.limit;
|
||||
else if (clientFilter && clientFilter.limit)
|
||||
limit = clientFilter.limit;
|
||||
|
||||
filter.where = (and.length > 0) && {and: and};
|
||||
filter.fields = fields;
|
||||
|
||||
this.find(filter, function(err, states) {
|
||||
if (err)
|
||||
cb(err, null);
|
||||
else
|
||||
cb(null, states);
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
Self.remoteMethodCtx = function(methodName, args) {
|
||||
let ctx = {
|
||||
arg: 'context',
|
||||
type: 'object',
|
||||
http: function(ctx) {
|
||||
return ctx;
|
||||
}
|
||||
};
|
||||
if (args.accepts === undefined)
|
||||
args.accepts = [];
|
||||
else if (!Array.isArray(args.accepts))
|
||||
args.accepts = [args.accepts];
|
||||
args.accepts.unshift(ctx);
|
||||
this.remoteMethod(methodName, args);
|
||||
};
|
||||
|
||||
Self.getConnection = function(cb) {
|
||||
this.dataSource.connector.client.getConnection(cb);
|
||||
};
|
||||
|
||||
Self.connectToService = function(ctx, dataSource) {
|
||||
this.app.dataSources[dataSource].connector.remotes.auth = {
|
||||
bearer: new Buffer(ctx.req.accessToken.id).toString('base64'),
|
||||
sendImmediately: true
|
||||
};
|
||||
};
|
||||
|
||||
Self.disconnectFromService = function(dataSource) {
|
||||
this.app.dataSources[dataSource].connector.remotes.auth = {
|
||||
bearer: new Buffer('').toString('base64'),
|
||||
sendImmediately: true
|
||||
};
|
||||
};
|
||||
|
||||
Self.crud = async function(actions) {
|
||||
async crud(deletes, updates, creates) {
|
||||
let transaction = await this.beginTransaction({});
|
||||
let options = {transaction: transaction};
|
||||
let options = {transaction};
|
||||
|
||||
try {
|
||||
if (actions.delete && actions.delete.length)
|
||||
await this.destroyAll({id: {inq: actions.delete}}, options);
|
||||
|
||||
if (actions.update) {
|
||||
try {
|
||||
if (deletes) {
|
||||
let promises = [];
|
||||
actions.update.forEach(toUpdate => {
|
||||
promises.push(this.upsertWithWhere(toUpdate.where, toUpdate.data, options));
|
||||
});
|
||||
for (let id of deletes)
|
||||
promises.push(this.destroyById(id, options));
|
||||
await Promise.all(promises);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
if (updates) {
|
||||
let promises = [];
|
||||
for (let update of updates)
|
||||
promises.push(this.upsertWithWhere(update.where, update.data, options));
|
||||
await Promise.all(promises);
|
||||
}
|
||||
if (actions.create && actions.create.length) {
|
||||
if (creates && creates.length)
|
||||
try {
|
||||
await this.create(actions.create, options);
|
||||
await this.create(creates, options);
|
||||
} catch (error) {
|
||||
throw error[error.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
await transaction.commit();
|
||||
} catch (error) {
|
||||
await transaction.rollback();
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Wrapper for remoteMethod() but adding the context as
|
||||
* extra argument at the beginning of arguments list.
|
||||
*
|
||||
* @param {String} methodName The method name
|
||||
* @param {Object} options The method options
|
||||
*/
|
||||
remoteMethodCtx(methodName, options) {
|
||||
if (options.accepts === undefined)
|
||||
options.accepts = [];
|
||||
else if (!Array.isArray(options.accepts))
|
||||
options.accepts = [options.accepts];
|
||||
|
||||
options.accepts.unshift({
|
||||
arg: 'ctx',
|
||||
type: 'Object',
|
||||
http: {source: 'context'}
|
||||
});
|
||||
this.remoteMethod(methodName, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a validation, marking it as exportable to the browser.
|
||||
* Exportable validation functions should be synchronous and totally
|
||||
* independent from other code because they are parsed in the browser
|
||||
* using eval().
|
||||
*
|
||||
* @param {String} propertyName The property name
|
||||
* @param {Function} validatorFn The validation function
|
||||
* @param {Object} options The validation options
|
||||
*/
|
||||
validateBinded(propertyName, validatorFn, options) {
|
||||
let customValidator = function(err) {
|
||||
if (!validatorFn(this[propertyName])) err();
|
||||
};
|
||||
options.isExportable = true;
|
||||
options.bindedFunction = validatorFn;
|
||||
this.validate(propertyName, customValidator, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Catches database errors overriding create() and upsert() methods.
|
||||
*
|
||||
* @param {Function} replaceErrFunc - Callback
|
||||
*/
|
||||
rewriteDbError(replaceErrFunc) {
|
||||
function replaceErr(err, replaceErrFunc) {
|
||||
if (Array.isArray(err)) {
|
||||
let errs = [];
|
||||
for (let e of err)
|
||||
errs.push(replaceErrFunc(e));
|
||||
return errs;
|
||||
}
|
||||
return replaceErrFunc(err);
|
||||
}
|
||||
|
||||
this.once('attached', () => {
|
||||
let realUpsert = this.upsert;
|
||||
this.upsert = async (data, options, cb) => {
|
||||
if (options instanceof Function) {
|
||||
cb = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
try {
|
||||
await realUpsert.call(this, data, options);
|
||||
if (cb) cb();
|
||||
} catch (err) {
|
||||
let myErr = replaceErr(err, replaceErrFunc);
|
||||
if (cb)
|
||||
cb(myErr);
|
||||
else
|
||||
throw myErr;
|
||||
}
|
||||
};
|
||||
|
||||
Self.checkAcls = async function(ctx, actionType) {
|
||||
let realCreate = this.create;
|
||||
this.create = async (data, options, cb) => {
|
||||
if (options instanceof Function) {
|
||||
cb = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
try {
|
||||
await realCreate.call(this, data, options);
|
||||
if (cb) cb();
|
||||
} catch (err) {
|
||||
let myErr = replaceErr(err, replaceErrFunc);
|
||||
if (cb)
|
||||
cb(myErr);
|
||||
else
|
||||
throw myErr;
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Shortcut to VnMySQL.executeP()
|
||||
*/
|
||||
rawSql(query, params, options, cb) {
|
||||
return this.dataSource.connector.executeP(query, params, options, cb);
|
||||
},
|
||||
|
||||
/*
|
||||
* Shortcut to VnMySQL.executeStmt()
|
||||
*/
|
||||
rawStmt(stmt, options) {
|
||||
return this.dataSource.connector.executeStmt(stmt, options);
|
||||
},
|
||||
|
||||
/*
|
||||
* Shortcut to VnMySQL.makeLimit()
|
||||
*/
|
||||
makeLimit(filter) {
|
||||
return this.dataSource.connector.makeLimit(filter);
|
||||
},
|
||||
|
||||
/*
|
||||
* Shortcut to VnMySQL.makeSuffix()
|
||||
*/
|
||||
makeSuffix(filter) {
|
||||
return this.dataSource.connector.makeSuffix(filter);
|
||||
},
|
||||
|
||||
/*
|
||||
* Shortcut to VnMySQL.buildModelSuffix()
|
||||
*/
|
||||
buildSuffix(filter, tableAlias) {
|
||||
return this.dataSource.connector.buildModelSuffix(this.modelName, filter, tableAlias);
|
||||
},
|
||||
|
||||
async checkAcls(ctx, actionType) {
|
||||
let userId = ctx.req.accessToken.userId;
|
||||
let models = this.app.models;
|
||||
let userRoles = await models.Account.getRoles(userId);
|
||||
|
@ -218,48 +258,14 @@ module.exports = function(Self) {
|
|||
|
||||
if (!allowedProperties)
|
||||
throw new UserError(`You don't have enough privileges`);
|
||||
};
|
||||
},
|
||||
|
||||
Self.checkUpdateAcls = function(ctx) {
|
||||
checkUpdateAcls(ctx) {
|
||||
return this.checkAcls(ctx, 'update');
|
||||
};
|
||||
},
|
||||
|
||||
Self.checkInsertAcls = function(ctx) {
|
||||
checkInsertAcls(ctx) {
|
||||
return this.checkAcls(ctx, 'insert');
|
||||
};
|
||||
|
||||
/*
|
||||
* Shortcut to VnMySQL.executeP()
|
||||
*/
|
||||
Self.rawSql = function(query, params, options, cb) {
|
||||
return this.dataSource.connector.executeP(query, params, options, cb);
|
||||
};
|
||||
|
||||
/*
|
||||
* Shortcut to VnMySQL.executeStmt()
|
||||
*/
|
||||
Self.rawStmt = function(stmt, options) {
|
||||
return this.dataSource.connector.executeStmt(stmt, options);
|
||||
};
|
||||
|
||||
/*
|
||||
* Shortcut to VnMySQL.makeLimit()
|
||||
*/
|
||||
Self.makeLimit = function(filter) {
|
||||
return this.dataSource.connector.makeLimit(filter);
|
||||
};
|
||||
|
||||
/*
|
||||
* Shortcut to VnMySQL.makeSuffix()
|
||||
*/
|
||||
Self.makeSuffix = function(filter) {
|
||||
return this.dataSource.connector.makeSuffix(filter);
|
||||
};
|
||||
|
||||
/*
|
||||
* Shortcut to VnMySQL.buildModelSuffix()
|
||||
*/
|
||||
Self.buildSuffix = function(filter, tableAlias) {
|
||||
return this.dataSource.connector.buildModelSuffix(this.modelName, filter, tableAlias);
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,18 +1,11 @@
|
|||
|
||||
const mysql = require('mysql');
|
||||
const loopbackConnector = require('loopback-connector');
|
||||
const SqlConnector = loopbackConnector.SqlConnector;
|
||||
const ParameterizedSQL = loopbackConnector.ParameterizedSQL;
|
||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
const MySQL = require('loopback-connector-mysql').MySQL;
|
||||
const EnumFactory = require('loopback-connector-mysql').EnumFactory;
|
||||
const fs = require('fs');
|
||||
|
||||
class VnMySQL extends MySQL {
|
||||
constructor(settings) {
|
||||
super();
|
||||
SqlConnector.call(this, 'mysql', settings);
|
||||
}
|
||||
|
||||
toColumnValue(prop, val) {
|
||||
if (val == null || !prop || prop.type !== Date)
|
||||
return MySQL.prototype.toColumnValue.call(this, prop, val);
|
||||
|
@ -237,12 +230,11 @@ exports.initialize = function initialize(dataSource, callback) {
|
|||
|
||||
dataSource.EnumFactory = EnumFactory;
|
||||
|
||||
if (callback) {
|
||||
if (callback)
|
||||
if (dataSource.settings.lazyConnect) {
|
||||
process.nextTick(function() {
|
||||
callback();
|
||||
});
|
||||
} else
|
||||
dataSource.connector.connect(callback);
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue