Merge branch 'dev' of https://git.verdnatura.es/salix into dev
This commit is contained in:
commit
a817cb58bf
|
@ -220,6 +220,57 @@
|
|||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/credit-classification",
|
||||
"abstract": true,
|
||||
"state": "clientCard.creditClassification",
|
||||
"component": "ui-view",
|
||||
"acl": ["creditInsurance"]
|
||||
},
|
||||
{
|
||||
"url": "/list",
|
||||
"state": "clientCard.creditClassification.list",
|
||||
"component": "vn-client-credit-classification-list",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Credit contracts",
|
||||
"icon": "security"
|
||||
},
|
||||
"acl": ["creditInsurance"]
|
||||
},
|
||||
{
|
||||
"url": "/create",
|
||||
"state": "clientCard.creditClassification.create",
|
||||
"component": "vn-client-credit-classification-create",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/credit-insurance",
|
||||
"abstract": true,
|
||||
"state": "clientCard.creditInsurance",
|
||||
"component": "ui-view",
|
||||
"acl": ["creditInsurance"]
|
||||
},
|
||||
{
|
||||
"url": "/:classificationId/list",
|
||||
"state": "clientCard.creditInsurance.list",
|
||||
"component": "vn-client-credit-insurance-list",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/:classificationId/create",
|
||||
"state": "clientCard.creditInsurance.create",
|
||||
"component": "vn-client-credit-insurance-create",
|
||||
"params": {
|
||||
"client": "$ctrl.client"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
<mg-ajax path="/client/api/ObservationTypes" options="mgIndex as observationsTypes"></mg-ajax>
|
||||
<vn-horizontal ng-repeat="observation in $ctrl.observations track by $index">
|
||||
<vn-autocomplete
|
||||
ng-if="!observation.id"
|
||||
vn-one
|
||||
initial-data="observation.observationType"
|
||||
field="observation.observationTypeFk"
|
||||
|
@ -61,6 +62,13 @@
|
|||
show-field="description"
|
||||
label="Observation type">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
ng-if="observation.id"
|
||||
vn-one
|
||||
label="Observation type"
|
||||
model="observation.observationType.description"
|
||||
disabled="true">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
margin-large-right
|
||||
|
|
|
@ -13,8 +13,8 @@ export default class Controller {
|
|||
id: parseInt($state.params.addressId)
|
||||
};
|
||||
this.observations = [];
|
||||
this.observationsOld = {};
|
||||
this.observationsRemoved = [];
|
||||
this.oldObservations = {};
|
||||
this.removedObservations = [];
|
||||
}
|
||||
|
||||
_setDirtyForm() {
|
||||
|
@ -22,6 +22,7 @@ export default class Controller {
|
|||
this.$scope.form.$setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
_unsetDirtyForm() {
|
||||
if (this.$scope.form) {
|
||||
this.$scope.form.$setPristine();
|
||||
|
@ -37,16 +38,17 @@ export default class Controller {
|
|||
if (item) {
|
||||
this.observations.splice(index, 1);
|
||||
if (item.id) {
|
||||
this.observationsRemoved.push(item.id);
|
||||
this.removedObservations.push(item.id);
|
||||
this._setDirtyForm();
|
||||
}
|
||||
}
|
||||
if (this.observations.length === 0 && Object.keys(this.observationsOld).length === 0) {
|
||||
if (this.observations.length === 0 && Object.keys(this.oldObservations).length === 0) {
|
||||
this._unsetDirtyForm();
|
||||
}
|
||||
}
|
||||
_submitObservations(objectObservations) {
|
||||
return this.$http.post(`/client/api/AddressObservations/crudAddressObservations`, objectObservations);
|
||||
|
||||
_submitObservations(observationsObject) {
|
||||
return this.$http.post(`/client/api/AddressObservations/crudAddressObservations`, observationsObject);
|
||||
}
|
||||
|
||||
_observationsEquals(ob1, ob2) {
|
||||
|
@ -58,12 +60,12 @@ export default class Controller {
|
|||
return false;
|
||||
}
|
||||
|
||||
let canWatcherSubmit = this.$scope.watcher.dataChanged();
|
||||
let canObservationsSubmit;
|
||||
let canSubmitWatcher = this.$scope.watcher.dataChanged();
|
||||
let canSubmitObservations;
|
||||
let repeatedTypes = false;
|
||||
let types = [];
|
||||
let observationsObj = {
|
||||
delete: this.observationsRemoved,
|
||||
delete: this.removedObservations,
|
||||
create: [],
|
||||
update: []
|
||||
};
|
||||
|
@ -82,26 +84,26 @@ export default class Controller {
|
|||
|
||||
if (isNewObservation && observation.observationTypeFk && observation.description) {
|
||||
observationsObj.create.push(observation);
|
||||
} else if (!isNewObservation && !this._observationsEquals(this.observationsOld[observation.id], observation)) {
|
||||
} else if (!isNewObservation && !this._observationsEquals(this.oldObservations[observation.id], observation)) {
|
||||
observationsObj.update.push(observation);
|
||||
}
|
||||
}
|
||||
|
||||
canObservationsSubmit = observationsObj.update.length > 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0;
|
||||
canSubmitObservations = observationsObj.update.length > 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0;
|
||||
|
||||
if (repeatedTypes) {
|
||||
this.vnApp.showMessage(
|
||||
this.$translate.instant('The observation type must be unique')
|
||||
);
|
||||
} else if (canWatcherSubmit && !canObservationsSubmit) {
|
||||
} else if (canSubmitWatcher && !canSubmitObservations) {
|
||||
this.$scope.watcher.submit().then(() => {
|
||||
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
|
||||
});
|
||||
} else if (!canWatcherSubmit && canObservationsSubmit) {
|
||||
} else if (!canSubmitWatcher && canSubmitObservations) {
|
||||
this._submitObservations(observationsObj).then(() => {
|
||||
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
|
||||
});
|
||||
} else if (canWatcherSubmit && canObservationsSubmit) {
|
||||
} else if (canSubmitWatcher && canSubmitObservations) {
|
||||
this.$q.all([this.$scope.watcher.submit(), this._submitObservations(observationsObj)]).then(() => {
|
||||
this.$state.go('clientCard.addresses.list', {id: this.$state.params.id});
|
||||
});
|
||||
|
@ -113,7 +115,7 @@ export default class Controller {
|
|||
this._unsetDirtyForm();
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
_getAddressNotes() {
|
||||
let filter = {
|
||||
where: {addressFk: this.address.id},
|
||||
include: {relation: 'observationType'}
|
||||
|
@ -121,10 +123,14 @@ export default class Controller {
|
|||
this.$http.get(`/client/api/AddressObservations?filter=${JSON.stringify(filter)}`).then(res => {
|
||||
this.observations = res.data;
|
||||
res.data.forEach(item => {
|
||||
this.observationsOld[item.id] = Object.assign({}, item);
|
||||
this.oldObservations[item.id] = Object.assign({}, item);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this._getAddressNotes();
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$state', '$scope', '$http', '$q', '$translate', 'vnApp'];
|
||||
|
||||
|
|
|
@ -23,3 +23,7 @@ import './invoices/invoices';
|
|||
import './summary/client-summary';
|
||||
import './recovery-list/recovery-list';
|
||||
import './recovery-create/recovery-create';
|
||||
import './credit-classification-list/credit-classification-list';
|
||||
import './credit-classification-create/credit-classification-create';
|
||||
import './credit-insurance-list/credit-insurance-list';
|
||||
import './credit-insurance-create/credit-insurance-create';
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<mg-ajax path="/client/api/clients/{{post.params.id}}/creditClassifications" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.creditClassification"
|
||||
form="form"
|
||||
save="post">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="watcher.submitGo('clientCard.creditClassification.list')" pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-title>New contract</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="Since"
|
||||
model="$ctrl.creditClassification.started"
|
||||
ini-options="{dateFormat: 'd-m-Y'}"
|
||||
vn-focus>
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,20 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($filter, $state) {
|
||||
this.creditClassification = {
|
||||
started: $filter('date')(new Date(), 'yyyy-MM-dd HH:mm')
|
||||
};
|
||||
this.$state = $state;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$filter', '$state'];
|
||||
|
||||
ngModule.component('vnClientCreditClassificationCreate', {
|
||||
template: require('./credit-classification-create.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,43 @@
|
|||
<vn-vertical pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-title vn-one>Contract credit insurance</vn-title>
|
||||
<vn-horizontal ng-repeat="classification in $ctrl.classifications track by classification.id" class="pad-medium-top" style="align-items: center;">
|
||||
<vn-one border-radius class="pad-small border-solid" ng-class="{'bg-dark-item': !classification.finished,'bg-opacity-item': classification.finished}">
|
||||
<vn-horizontal style="align-items: center;">
|
||||
<vn-none pad-medium-h style="color:#FFA410;">
|
||||
<i class="material-icons pointer"
|
||||
ng-if="!classification.finished"
|
||||
vn-tooltip="Close contract"
|
||||
tooltip-position="left"
|
||||
ng-click="$ctrl.closeContract(classification)">lock_outline</i>
|
||||
</vn-none>
|
||||
<vn-one border-solid-right>
|
||||
<div><vn-label translate>Since</vn-label> {{::classification.started | date:'dd/MM/yyyy'}}</div>
|
||||
<div><vn-label translate>To</vn-label> {{classification.finished | date:'dd/MM/yyyy'}}</div>
|
||||
</vn-one>
|
||||
<vn-vertical vn-one pad-medium-h>
|
||||
<vn-one ng-repeat="insurance in classification.creditInsurances track by insurance.id">
|
||||
<vn-label translate>Credit</vn-label> <span>{{insurance.credit}}</span>
|
||||
<vn-label translate>Grade</vn-label>
|
||||
<span ng-if="!insurance.grade">-</span>
|
||||
<span ng-if="insurance.grade">{{insurance.grade}}</span>
|
||||
<vn-label translate>Date</vn-label> <span>{{insurance.created | date:'dd/MM/yyyy' }}</span>
|
||||
</vn-one>
|
||||
</vn-vertical>
|
||||
<a vn-auto ui-sref="clientCard.creditInsurance.list({classificationId: {{classification.id}}})">
|
||||
<vn-icon-button icon="edit" vn-tooltip="Edit contract" tooltip-position="left"></vn-icon-button>
|
||||
</a>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-float-button
|
||||
ng-if="$ctrl.canCreateNew()"
|
||||
vn-tooltip="New contract"
|
||||
tooltip-position="left"
|
||||
fixed-bottom-right
|
||||
ui-sref="clientCard.creditClassification.create"
|
||||
icon="add"
|
||||
label="Add">
|
||||
</vn-float-button>
|
||||
</vn-vertical>
|
|
@ -0,0 +1,68 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
|
||||
constructor($http, $scope) {
|
||||
this.$http = $http;
|
||||
this.$scope = $scope;
|
||||
}
|
||||
|
||||
$onChanges() {
|
||||
if (this.client && this.client.id)
|
||||
this._getClassifications(this.client.id);
|
||||
}
|
||||
|
||||
_getClassifications(clientId) {
|
||||
let filter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'creditInsurances',
|
||||
scope: {
|
||||
fields: ['id', 'credit', 'created', 'grade'],
|
||||
order: 'created DESC',
|
||||
limit: 2
|
||||
}
|
||||
}
|
||||
|
||||
],
|
||||
where: {client: clientId}
|
||||
};
|
||||
filter = encodeURIComponent(JSON.stringify(filter));
|
||||
|
||||
let query = `/client/api/CreditClassifications?filter=${filter}`;
|
||||
this.$http.get(query).then(res => {
|
||||
if (res.data)
|
||||
this.classifications = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
canCreateNew() {
|
||||
if (!this.classifications)
|
||||
return false;
|
||||
|
||||
let items = this.classifications;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (!items[i].finished)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
closeContract(classification) {
|
||||
let params = {finished: Date.now()};
|
||||
this.$http.patch(`/client/api/CreditClassifications/${classification.id}`, params).then(() => {
|
||||
this._getClassifications(this.client.id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$http', '$scope'];
|
||||
|
||||
ngModule.component('vnClientCreditClassificationList', {
|
||||
template: require('./credit-classification-list.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,80 @@
|
|||
import './credit-classification-list.js';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientCreditClassificationList', () => {
|
||||
let $componentController;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('client');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
controller = $componentController('vnClientCreditClassificationList');
|
||||
}));
|
||||
|
||||
describe('_getClassifications()', () => {
|
||||
it('should perform a GET query to define the classifications property in the controller', () => {
|
||||
let res = ['some classifications'];
|
||||
let query = '/client/api/CreditClassifications?filter=%7B%22include%22%3A%5B%7B%22relation%22%3A%22creditInsurances%22%2C%22scope%22%3A%7B%22fields%22%3A%5B%22id%22%2C%22credit%22%2C%22created%22%2C%22grade%22%5D%2C%22order%22%3A%22created%20DESC%22%2C%22limit%22%3A2%7D%7D%5D%2C%22where%22%3A%7B%7D%7D';
|
||||
|
||||
$httpBackend.whenGET(query).respond(res);
|
||||
$httpBackend.expectGET(query);
|
||||
controller._getClassifications();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.classifications).toEqual(['some classifications']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('canCreateNew()', () => {
|
||||
it(`should return false if doesn't have classifications`, () => {
|
||||
let result = controller.canCreateNew();
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it(`should return false if finds a classification without due date`, () => {
|
||||
controller.classifications = [
|
||||
{finished: Date.now()},
|
||||
{finished: null}
|
||||
];
|
||||
|
||||
let result = controller.canCreateNew();
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it(`should return true if all classifications are defined with due date`, () => {
|
||||
controller.classifications = [
|
||||
{finished: Date.now()},
|
||||
{finished: Date.now()}
|
||||
];
|
||||
|
||||
let result = controller.canCreateNew();
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('closeContract()', () => {
|
||||
it('should perform a GET query to set a due date to a contract', () => {
|
||||
let res = ['pepinillos'];
|
||||
controller.client = {id: 101};
|
||||
let classification = {id: 1};
|
||||
let query = '/client/api/CreditClassifications/1';
|
||||
spyOn(controller, '_getClassifications');
|
||||
|
||||
$httpBackend.whenPATCH(query).respond(res);
|
||||
$httpBackend.expectPATCH(query);
|
||||
controller.closeContract(classification);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller._getClassifications).toHaveBeenCalledWith(101);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,4 @@
|
|||
Contract credit insurance: Contratos de seguro de crédito
|
||||
New contract: Nuevo contrato
|
||||
Close contract: Cerrar contrato
|
||||
Edit contract: Modificar contrato
|
|
@ -0,0 +1,42 @@
|
|||
<mg-ajax path="/client/api/CreditClassifications/{{post.params.classificationId}}/creditInsurances" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.insurance"
|
||||
form="form"
|
||||
save="post">
|
||||
</vn-watcher>
|
||||
<form name="form"
|
||||
ng-submit="watcher.submitGo('clientCard.creditInsurance.list', {classificationId: post.params.classificationId})"
|
||||
pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-title>New credit</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
margin-medium-right
|
||||
label="Credit"
|
||||
model="$ctrl.insurance.credit",
|
||||
rule="CreditInsurance.credit"
|
||||
step="1"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-date-picker vn-one
|
||||
label="Date"
|
||||
model="$ctrl.insurance.created"
|
||||
ini-options="{enableTime: true, dateFormat: 'd-m-Y h:i', time_24hr: true}">
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
argin-medium-right
|
||||
label="Grade"
|
||||
model="$ctrl.insurance.grade"
|
||||
rule="CreditInsurance.grade">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,20 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($state, $filter) {
|
||||
this.insurance = {
|
||||
created: $filter('date')(new Date(), 'yyyy-MM-dd HH:mm')
|
||||
};
|
||||
this.classificationId = $state.params.classificationId;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$state', '$filter'];
|
||||
|
||||
ngModule.component('vnClientCreditInsuranceCreate', {
|
||||
template: require('./credit-insurance-create.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
New credit: Añadir crédito
|
|
@ -0,0 +1,28 @@
|
|||
<mg-ajax path="/client/api/CreditClassifications/{{index.params.classificationId}}/creditInsurances" options="vnIndex"></mg-ajax>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-title>Requested credits</vn-title>
|
||||
<vn-grid-header>
|
||||
<vn-column-header vn-one pad-medium-h text="Amount"></vn-column-header>
|
||||
<vn-column-header vn-one pad-medium-h text="Grade"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h text="Date"></vn-column-header>
|
||||
</vn-grid-header>
|
||||
<vn-one class="list list-content">
|
||||
<vn-horizontal
|
||||
vn-one class="list list-element text-center"
|
||||
pad-small-bottom
|
||||
ng-repeat="insurance in index.model track by insurance.id">
|
||||
<vn-one pad-medium-h>{{insurance.credit}}</vn-one>
|
||||
<vn-one pad-medium-h>{{insurance.grade}}</vn-one>
|
||||
<vn-two pad-medium-h>{{insurance.created | date: 'dd/MM/yyyy'}}</vn-two>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-horizontal vn-one class="list list-footer"></vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
<a ui-sref="clientCard.creditInsurance.create({classificationId: {{index.params.classificationId}}})"
|
||||
fixed-bottom-right vn-tooltip="New credit" tooltip-position="left">
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
|
@ -0,0 +1,17 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($state) {
|
||||
this.classificationId = $state.params.classificationId;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$state'];
|
||||
|
||||
ngModule.component('vnClientCreditInsuranceList', {
|
||||
template: require('./credit-insurance-list.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
Requested credits: Créditos solicitados
|
|
@ -25,30 +25,36 @@
|
|||
<span ng-if="!$ctrl.client.creditInsurance">-</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<vn-horizontal pad-medium-bottom class="footer">
|
||||
<vn-icon
|
||||
vn-tooltip="Client inactive"
|
||||
tooltip-position = "right"
|
||||
icon="person"
|
||||
icon="icon-disabled"
|
||||
ng-class="{bright: $ctrl.client.isActive == false}">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Client Frozen"
|
||||
tooltip-position = "right"
|
||||
icon="mail"
|
||||
icon="icon-frozen"
|
||||
ng-class="{bright: $ctrl.client.isFreezed == true}">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Web Account inactive"
|
||||
tooltip-position = "right"
|
||||
icon="phone"
|
||||
icon="icon-noweb"
|
||||
ng-class="{bright: $ctrl.client.account.active == false}">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
vn-tooltip="Client has debt"
|
||||
tooltip-position = "right"
|
||||
icon="power"
|
||||
icon="icon-risk"
|
||||
ng-class="{bright: $ctrl.clientDebt < 0}">
|
||||
</vn-icon>
|
||||
</div>
|
||||
<vn-icon
|
||||
vn-tooltip="Client not checked"
|
||||
tooltip-position = "right"
|
||||
icon="icon-no036"
|
||||
ng-class="{bright: $ctrl.client.isTaxDataChecked == false}">
|
||||
</vn-icon>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
|
@ -89,13 +89,20 @@
|
|||
</vn-check>
|
||||
<vn-check
|
||||
vn-one
|
||||
label="Frozen"
|
||||
field="$ctrl.client.isFreezed"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
vn-two
|
||||
label="Invoice by address"
|
||||
field="$ctrl.client.hasToInvoiceByAddress"
|
||||
vn-acl="administrative, salesAssistant, salesPerson"
|
||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
vn-one
|
||||
vn-two
|
||||
label="Verified data"
|
||||
field="$ctrl.client.isTaxDataChecked"
|
||||
vn-acl="administrative, salesAssistant, salesAssistant">
|
||||
|
|
|
@ -17,7 +17,7 @@ Save: Guardar
|
|||
Pay method : Forma de pago
|
||||
Address: Consignatario
|
||||
Credit : Crédito
|
||||
Secured credit: Crédito asegurado
|
||||
Credit contracts: Contratos de crédito
|
||||
Verified data: Datos comprobados
|
||||
Mandate: Mandato
|
||||
Amount: Importe
|
|
@ -123,8 +123,8 @@
|
|||
<vn-one margin-medium>
|
||||
<h5 translate>Recovery</h5>
|
||||
<vn-vertical ng-if="$ctrl.recovery">
|
||||
<p><vn-label translate>Since</vn-label> {{$ctrl.recovery.started}}</p>
|
||||
<p><vn-label translate>To</vn-label> {{$ctrl.recovery.finished}}</p>
|
||||
<p><vn-label translate>Since</vn-label> {{$ctrl.recovery.started | date:'dd/MM/yyyy'}}</p>
|
||||
<p><vn-label translate>To</vn-label> {{$ctrl.recovery.finished | date:'dd/MM/yyyy'}}</p>
|
||||
<p><vn-label translate>Amount</vn-label> {{$ctrl.recovery.amount | currency:'€':2}}</p>
|
||||
<p><vn-label translate>Period</vn-label> {{$ctrl.recovery.period}}</p>
|
||||
</vn-vertical>
|
||||
|
@ -145,8 +145,8 @@
|
|||
</p>
|
||||
<p>
|
||||
<vn-label translate>Secured credit</vn-label>
|
||||
<b ng-if="!$ctrl.summary.creditInsurance">-</b>
|
||||
<b ng-if="$ctrl.summary.creditInsurance">{{$ctrl.summary.creditInsurance | currency:'€':2}}
|
||||
<span ng-if="!$ctrl.summary.creditInsurance">-</span>
|
||||
<span ng-if="$ctrl.summary.creditInsurance">{{$ctrl.summary.creditInsurance | currency:'€':2}}</span>
|
||||
</p>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -1,53 +1,29 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class ClientSummary {
|
||||
class Controller {
|
||||
|
||||
constructor($http) {
|
||||
this.$http = $http;
|
||||
}
|
||||
|
||||
set client(value) {
|
||||
if (!value)
|
||||
$onChanges() {
|
||||
if (!this.client || !this.client.id)
|
||||
return;
|
||||
|
||||
this.getSummary();
|
||||
this.getGreuse();
|
||||
this.getRecoveries();
|
||||
}
|
||||
|
||||
getSummary() {
|
||||
let filter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'account',
|
||||
scope: {
|
||||
fields: ['name', 'active']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'salesPerson',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'country',
|
||||
scope: {
|
||||
fields: ['country']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'province',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'contactChannel',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'payMethod',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
{relation: 'account', scope: {fields: ['name', 'active']}},
|
||||
{relation: 'salesPerson', scope: {fields: ['name']}},
|
||||
{relation: 'country', scope: {fields: ['country']}},
|
||||
{relation: 'province', scope: {fields: ['name']}},
|
||||
{relation: 'contactChannel', scope: {fields: ['name']}},
|
||||
{relation: 'payMethod', scope: {fields: ['name']}},
|
||||
{
|
||||
relation: 'addresses',
|
||||
scope: {
|
||||
|
@ -57,43 +33,46 @@ class ClientSummary {
|
|||
}
|
||||
]
|
||||
};
|
||||
filter = encodeURIComponent(JSON.stringify(filter));
|
||||
|
||||
let clientSummary = `/client/api/Clients/${value.id}?filter=${JSON.stringify(filter)}`;
|
||||
|
||||
this.$http.get(encodeURIComponent(clientSummary)).then(res => {
|
||||
let query = `/client/api/Clients/${this.client.id}?filter=${filter}`;
|
||||
this.$http.get(query).then(res => {
|
||||
if (res.data) {
|
||||
this.summary = res.data;
|
||||
this.address = res.data.addresses[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let greugeSum = `/client/api/Greuges/${value.id}/sumAmount`;
|
||||
|
||||
this.$http.get(encodeURIComponent(greugeSum)).then(res => {
|
||||
getGreuse() {
|
||||
let query = `/client/api/Greuges/${this.client.id}/sumAmount`;
|
||||
this.$http.get(query).then(res => {
|
||||
if (res.data)
|
||||
this.greuge = res.data;
|
||||
});
|
||||
}
|
||||
|
||||
let recoveryFilter = {
|
||||
getRecoveries() {
|
||||
let filter = {
|
||||
where: {
|
||||
and: [{clientFk: value.id}, {or: [{finished: null}, {finished: {gt: Date.now()}}]}]
|
||||
and: [{clientFk: this.client.id}, {or: [{finished: null}, {finished: {gt: Date.now()}}]}]
|
||||
},
|
||||
limit: 1
|
||||
};
|
||||
filter = encodeURIComponent(JSON.stringify(filter));
|
||||
|
||||
let recovery = `/client/api/Recoveries?filter=${JSON.stringify(recoveryFilter)}`;
|
||||
|
||||
this.$http.get(encodeURIComponent(recovery)).then(res => {
|
||||
let query = `/client/api/Recoveries?filter=${filter}`;
|
||||
this.$http.get(query).then(res => {
|
||||
if (res.data)
|
||||
this.recovery = res.data[0];
|
||||
});
|
||||
}
|
||||
}
|
||||
ClientSummary.$inject = ['$http'];
|
||||
Controller.$inject = ['$http'];
|
||||
|
||||
ngModule.component('vnClientSummary', {
|
||||
template: require('./client-summary.html'),
|
||||
controller: ClientSummary,
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
client: '<'
|
||||
}
|
||||
|
|
|
@ -3,3 +3,4 @@ Enable web access: Habilitar acceso web
|
|||
New password: Nueva contraseña
|
||||
Repeat password: Repetir contraseña
|
||||
Change password: Cambiar contraseña
|
||||
Client must be checked to activate: No se puede activar un cliente si no esta verificado (036)
|
|
@ -23,6 +23,7 @@
|
|||
vn-one
|
||||
margin-medium-top
|
||||
label="User"
|
||||
info="Client must be checked to activate"
|
||||
field="$ctrl.account.name">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
</div>
|
||||
<label class="mdl-textfield__label" translate>{{::$ctrl.label}}</label>
|
||||
</div>
|
||||
<vn-drop-down
|
||||
</div>
|
||||
<vn-drop-down
|
||||
vn-id="drop-down"
|
||||
on-select="$ctrl.onDropDownSelect(value)">
|
||||
</vn-drop-down>
|
||||
</div>
|
||||
</vn-drop-down>
|
|
@ -45,6 +45,9 @@ export default class DropDown extends Component {
|
|||
this._search = value;
|
||||
this.$.model.clear();
|
||||
|
||||
if (value != null)
|
||||
this._activeOption = 0;
|
||||
|
||||
this.$timeout.cancel(this.searchTimeout);
|
||||
this.searchTimeout = this.$timeout(() => {
|
||||
this.refreshModel();
|
||||
|
@ -86,8 +89,8 @@ export default class DropDown extends Component {
|
|||
* @param {String} search The initial search term or %null
|
||||
*/
|
||||
show(search) {
|
||||
this.search = search;
|
||||
this._activeOption = -1;
|
||||
this.search = search;
|
||||
this.buildList();
|
||||
this.$.popover.parent = this.parent;
|
||||
this.$.popover.show();
|
||||
|
@ -101,7 +104,7 @@ export default class DropDown extends Component {
|
|||
}
|
||||
|
||||
/**
|
||||
* Activates a option and scrolls the drop-down to that option.
|
||||
* Activates an option and scrolls the drop-down to that option.
|
||||
*
|
||||
* @param {Number} option The option index
|
||||
*/
|
||||
|
@ -122,7 +125,7 @@ export default class DropDown extends Component {
|
|||
}
|
||||
|
||||
/**
|
||||
* Activates a option.
|
||||
* Activates an option.
|
||||
*
|
||||
* @param {Number} option The option index
|
||||
*/
|
||||
|
@ -146,10 +149,11 @@ export default class DropDown extends Component {
|
|||
* @param {Number} option The option index
|
||||
*/
|
||||
selectOption(option) {
|
||||
if (option != -1) {
|
||||
let data = this.$.model.data;
|
||||
let item = data ? data[option] : null;
|
||||
let value = item ? item[this.valueField] : null;
|
||||
let item = option != -1 && data ? data[option] : null;
|
||||
|
||||
if (item) {
|
||||
let value = item[this.valueField];
|
||||
|
||||
if (this.multiple) {
|
||||
if (!Array.isArray(this.selection)) {
|
||||
|
@ -252,6 +256,9 @@ export default class DropDown extends Component {
|
|||
let nOpts = data ? data.length - 1 : 0;
|
||||
|
||||
switch (event.keyCode) {
|
||||
case 9: // Tab
|
||||
this.selectOption(option);
|
||||
return;
|
||||
case 13: // Enter
|
||||
this.selectOption(option);
|
||||
break;
|
||||
|
|
|
@ -88,6 +88,9 @@ export default class Popover extends Component {
|
|||
this.showTimeout = this.$timeout(() => {
|
||||
this.element.style.display = 'none';
|
||||
this.showTimeout = null;
|
||||
|
||||
if (this.onClose)
|
||||
this.onClose();
|
||||
}, 250);
|
||||
|
||||
this.document.removeEventListener('keydown', this.docKeyDownHandler);
|
||||
|
@ -95,12 +98,6 @@ export default class Popover extends Component {
|
|||
|
||||
if (this.deregisterCallback)
|
||||
this.deregisterCallback();
|
||||
|
||||
if (this.parent)
|
||||
this.parent.focus();
|
||||
|
||||
if (this.onClose)
|
||||
this.onClose();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,35 +186,3 @@ ngModule.component('vnPopover', {
|
|||
onClose: '&?'
|
||||
}
|
||||
});
|
||||
|
||||
class PopoverService {
|
||||
constructor($document, $compile, $transitions, $rootScope) {
|
||||
this.$compile = $compile;
|
||||
this.$rootScope = $rootScope;
|
||||
this.$document = $document;
|
||||
this.stack = [];
|
||||
}
|
||||
show(child, parent, $scope) {
|
||||
let element = this.$compile('<vn-popover/>')($scope || this.$rootScope)[0];
|
||||
let popover = element.$ctrl;
|
||||
popover.parent = parent;
|
||||
popover.child = child;
|
||||
popover.show();
|
||||
popover.onClose = () => {
|
||||
this.$document[0].body.removeChild(element);
|
||||
if ($scope) $scope.$destroy();
|
||||
};
|
||||
this.$document[0].body.appendChild(element);
|
||||
return popover;
|
||||
}
|
||||
|
||||
showComponent(componentTag, $scope, parent) {
|
||||
let $newScope = $scope.$new();
|
||||
let childElement = this.$compile(`<${componentTag}/>`)($newScope)[0];
|
||||
this.show(childElement, parent, $newScope);
|
||||
return childElement;
|
||||
}
|
||||
}
|
||||
PopoverService.$inject = ['$document', '$compile', '$transitions', '$rootScope'];
|
||||
|
||||
ngModule.service('vnPopover', PopoverService);
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
|
||||
.icon-barcode:before { content: '\e800'; } /* '' */
|
||||
.icon-tags:before { content: '\e800'; } /* '' */
|
||||
.icon-volume:before { content: '\e801'; } /* '' */
|
||||
.icon-bucket:before { content: '\e802'; } /* '' */
|
||||
.icon-barcode:before { content: '\e802'; } /* '' */
|
||||
.icon-bucket:before { content: '\e803'; } /* '' */
|
||||
.icon-frozen:before { content: '\e808'; } /* '' */
|
||||
.icon-disabled:before { content: '\e80b'; } /* '' */
|
||||
.icon-invoices:before { content: '\e80c'; } /* '' */
|
||||
.icon-noweb:before { content: '\e812'; } /* '' */
|
||||
|
@ -15,4 +17,6 @@
|
|||
.icon-addperson:before { content: '\e81e'; } /* '' */
|
||||
.icon-bin:before { content: '\e81f'; } /* '' */
|
||||
.icon-sms:before { content: '\e820'; } /* '' */
|
||||
.icon-tags:before { content: '\e821'; } /* '' */
|
||||
.icon-ticket:before { content: '\e821'; } /* '' */
|
||||
.icon-tax:before { content: '\e822'; } /* '' */
|
||||
.icon-no036:before { content: '\e823'; } /* '' */
|
Binary file not shown.
|
@ -58,7 +58,7 @@
|
|||
"component": "vn-item-tax",
|
||||
"menu": {
|
||||
"description": "Tax",
|
||||
"icon": "folder"
|
||||
"icon": "icon-tax"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@ export default class Controller {
|
|||
this.removedBarcodes = [];
|
||||
this.oldBarcodes = {};
|
||||
}
|
||||
|
||||
_setIconAdd() {
|
||||
if (this.barcodes.length) {
|
||||
this.barcodes.map(element => {
|
||||
|
@ -30,11 +31,13 @@ export default class Controller {
|
|||
this.$scope.form.$setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
_unsetDirtyForm() {
|
||||
if (this.$scope.form) {
|
||||
this.$scope.form.$setPristine();
|
||||
}
|
||||
}
|
||||
|
||||
_equalBarcodes(oldBarcode, newBarcode) {
|
||||
return oldBarcode.id === newBarcode.id && oldBarcode.code === newBarcode.code;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
<vn-title>Item Niches</vn-title>
|
||||
<vn-horizontal ng-repeat="itemNiche in $ctrl.niches track by $index">
|
||||
<vn-autocomplete
|
||||
vn-three
|
||||
ng-if="!itemNiche.id"
|
||||
vn-one
|
||||
data="$ctrl.warehouses"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
|
@ -18,7 +19,14 @@
|
|||
vn-acl="buyer,replenisher">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
vn-three
|
||||
ng-if="itemNiche.id"
|
||||
vn-one
|
||||
label="Warehouse"
|
||||
model="itemNiche.warehouse.name"
|
||||
disabled="true">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
label="code"
|
||||
model="itemNiche.code"
|
||||
rule="itemNiche.code"
|
||||
|
|
|
@ -31,6 +31,7 @@ export default class Controller {
|
|||
this.$scope.form.$setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
_unsetDirtyForm() {
|
||||
if (this.$scope.form) {
|
||||
this.$scope.form.$setPristine();
|
||||
|
@ -70,6 +71,7 @@ export default class Controller {
|
|||
where: {itemFk: this.params.id},
|
||||
include: {relation: 'warehouse'}
|
||||
};
|
||||
|
||||
this.$http.get(`/item/api/ItemNiches?filter=${JSON.stringify(filter)}`).then(response => {
|
||||
this.niches = response.data;
|
||||
this.setOldNiches(response);
|
||||
|
@ -95,6 +97,7 @@ export default class Controller {
|
|||
create: [],
|
||||
update: []
|
||||
};
|
||||
|
||||
this.niches.forEach(niche => {
|
||||
let isNewNiche = !niche.id;
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ describe('Item', () => {
|
|||
});
|
||||
|
||||
describe('submit()', () => {
|
||||
it("should return an error message 'The niche must be unique' when the niche code isnt unique", () => {
|
||||
it("should return an error message 'The niche must be unique' when the niche warehouse isnt unique", () => {
|
||||
controller.$scope.form = {};
|
||||
spyOn(controller.vnApp, 'showMessage').and.callThrough();
|
||||
controller.niches = [
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<vn-title>Item tags</vn-title>
|
||||
<vn-horizontal ng-repeat="itemTag in $ctrl.instancedItemTags track by $index">
|
||||
<vn-autocomplete
|
||||
ng-if="!itemTag.id"
|
||||
vn-one
|
||||
initial-data="itemTag.tag"
|
||||
field="itemTag.tagFk"
|
||||
|
@ -16,6 +17,13 @@
|
|||
label="Tag"
|
||||
vn-acl="buyer">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
ng-if="itemTag.id"
|
||||
vn-one
|
||||
label="Tag"
|
||||
model="itemTag.tag.name"
|
||||
disabled="true">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-three
|
||||
label="Value"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<form ng-submit="$ctrl.onSubmit()">
|
||||
<vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield vn-one label="Search" model="$ctrl.stringSearch"></vn-textfield>
|
||||
<vn-icon
|
||||
pad-medium-top
|
||||
|
@ -10,5 +10,9 @@
|
|||
</vn-icon>
|
||||
<vn-button ng-if="$ctrl.label" vn-none label="{{$ctrl.label}}"></vn-button>
|
||||
<vn-icon-button ng-if="!$ctrl.label" icon="search" ng-click="$ctrl.clearFilter()"></vn-icon-button>
|
||||
</vn-horizontal>
|
||||
</vn-horizontal>
|
||||
</form>
|
||||
<vn-popover
|
||||
vn-id="popover"
|
||||
on-close="$ctrl.onPopoverClose()">
|
||||
</vn-popover>
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import ngModule from '../../module';
|
||||
|
||||
export default class Controller {
|
||||
constructor($element, $scope, $document, $compile, vnPopover, $timeout, $state, $transitions) {
|
||||
constructor($element, $scope, $compile, $timeout, $state, $transitions) {
|
||||
this.element = $element[0];
|
||||
this.$scope = $scope;
|
||||
this.$document = $document;
|
||||
this.$ = $scope;
|
||||
this.$compile = $compile;
|
||||
this.vnPopover = vnPopover;
|
||||
this.$timeout = $timeout;
|
||||
this.stringSearch = '';
|
||||
this.$state = $state;
|
||||
|
@ -91,23 +89,32 @@ export default class Controller {
|
|||
filter = this.getFiltersFromString(this.stringSearch);
|
||||
}
|
||||
|
||||
this.child = this.vnPopover.showComponent(this.popover, this.$scope, this.element);
|
||||
this.$child = this.$compile(`<${this.popover}/>`)(this.$.$new());
|
||||
|
||||
// XXX: ¿Existe una forma más adecuada de acceder al controlador de un componente?
|
||||
var childCtrl = angular.element(this.child).isolateScope().$ctrl;
|
||||
var childCtrl = this.$child.isolateScope().$ctrl;
|
||||
childCtrl.filter = Object.assign({}, filter);
|
||||
childCtrl.onSubmit = filter => this.onChildSubmit(filter);
|
||||
if (this.data)
|
||||
childCtrl.data = Object.assign({}, this.data);
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
this.$.popover.parent = this.element;
|
||||
this.$.popover.child = this.$child[0];
|
||||
this.$.popover.show();
|
||||
}
|
||||
|
||||
onPopoverClose() {
|
||||
this.$child.scope().$destroy();
|
||||
this.$child.remove();
|
||||
this.$child = null;
|
||||
}
|
||||
|
||||
onChildSubmit(filter) {
|
||||
this.$.popover.hide();
|
||||
this.stringSearch = this.createStringFromObject(filter);
|
||||
this.clearFilter();
|
||||
this.$timeout(() => {
|
||||
this.onSubmit();
|
||||
});
|
||||
this.$timeout(() => this.onSubmit());
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
|
@ -120,12 +127,6 @@ export default class Controller {
|
|||
if (this.onSearch)
|
||||
this.onSearch();
|
||||
|
||||
if (angular.element(this.child)) {
|
||||
if (angular.element(this.child).scope())
|
||||
angular.element(this.child).scope().$destroy();
|
||||
angular.element(this.child).remove();
|
||||
}
|
||||
delete this.child;
|
||||
this.pushFiltersToState(filter);
|
||||
}
|
||||
|
||||
|
@ -139,12 +140,10 @@ export default class Controller {
|
|||
let filter = JSON.parse(decodeURIComponent(this.$state.params.q));
|
||||
this.stringSearch = this.createStringFromObject(filter);
|
||||
}
|
||||
this.$timeout(() => {
|
||||
this.onSubmit();
|
||||
});
|
||||
this.$timeout(() => this.onSubmit());
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$element', '$scope', '$document', '$compile', 'vnPopover', '$timeout', '$state', '$transitions'];
|
||||
Controller.$inject = ['$element', '$scope', '$compile', '$timeout', '$state', '$transitions'];
|
||||
|
||||
ngModule.component('vnSearchbar', {
|
||||
template: require('./searchbar.html'),
|
||||
|
|
|
@ -19,3 +19,8 @@ phone: Teléfono
|
|||
creditInsurance: Crédito Asegurado
|
||||
Return to module index: Volver a la página principal del módulo
|
||||
Preview: Vista previa
|
||||
Client has debt: Cliente con riesgo
|
||||
Web Account inactive: Sin acceso Web
|
||||
Client Frozen: Cliente congelado
|
||||
Client inactive: Cliente inactivo
|
||||
Client not checked: Cliente no comprobado
|
|
@ -215,7 +215,7 @@ vn-main-block {
|
|||
color: #ffa410;
|
||||
margin-left: .5em;
|
||||
transition: opacity 250ms ease-out;
|
||||
|
||||
font-size: 2em;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,92 @@
|
|||
{
|
||||
"module": "ticket",
|
||||
"name": "Tickets",
|
||||
"icon": "receipt",
|
||||
"icon": "icon-ticket",
|
||||
"validations": false,
|
||||
"routes": [
|
||||
{
|
||||
"url": "/tickets",
|
||||
"state": "tickets",
|
||||
"component": "vn-ticket-index",
|
||||
"acl": ["developer"]
|
||||
"url": "/ticket",
|
||||
"state": "ticket",
|
||||
"abstract": true,
|
||||
"component": "ui-view"
|
||||
},
|
||||
{
|
||||
"url": "/list?q",
|
||||
"state": "ticket.list",
|
||||
"component": "vn-ticket-list"
|
||||
},
|
||||
{
|
||||
"url": "/create",
|
||||
"state": "ticket.create",
|
||||
"component": "vn-ticket-create"
|
||||
},
|
||||
{
|
||||
"url": "/:id",
|
||||
"state": "ticket.card",
|
||||
"abstract": true,
|
||||
"component": "vn-ticket-card"
|
||||
},
|
||||
{
|
||||
"url": "/summary",
|
||||
"state": "ticket.card.summary",
|
||||
"component": "vn-ticket-summary",
|
||||
"params": {
|
||||
"ticket": "$ctrl.ticket"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url" : "/data",
|
||||
"state": "ticket.card.data",
|
||||
"component": "vn-ticket-data",
|
||||
"params": {
|
||||
"ticket": "$ctrl.ticket"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Basic data",
|
||||
"icon": "settings"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "/observations",
|
||||
"state": "ticket.card.observations",
|
||||
"component": "vn-ticket-observations",
|
||||
"params": {
|
||||
"ticket": "$ctrl.ticket"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Notes",
|
||||
"icon": "insert_drive_file"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url" : "/package",
|
||||
"abstract": true,
|
||||
"state": "ticket.card.package",
|
||||
"component": "ui-view"
|
||||
},
|
||||
{
|
||||
"url": "/list",
|
||||
"state": "ticket.card.package.list",
|
||||
"component": "vn-ticket-package-list",
|
||||
"params": {
|
||||
"ticket": "$ctrl.ticket"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Packages",
|
||||
"icon": "icon-bucket"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url" : "/review",
|
||||
"state": "ticket.card.review",
|
||||
"component": "vn-ticket-review",
|
||||
"params": {
|
||||
"ticket": "$ctrl.ticket"
|
||||
},
|
||||
"menu": {
|
||||
"description": "Review",
|
||||
"icon": "remove_red_eye"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<vn-main-block>
|
||||
<vn-horizontal>
|
||||
<vn-auto margin-medium-v class="left-block">
|
||||
<vn-item-descriptor ticket="$ctrl.ticket"></vn-ticket-descriptor>
|
||||
<vn-left-menu></vn-left-menu>
|
||||
</vn-auto>
|
||||
<vn-one>
|
||||
<vn-vertical margin-medium ui-view></vn-vertical>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-main-block>
|
|
@ -0,0 +1,35 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class TicketCard {
|
||||
constructor($http, $state, $timeout) {
|
||||
this.$http = $http;
|
||||
this.$state = $state;
|
||||
this.$timeout = $timeout;
|
||||
|
||||
this.ticket = null;
|
||||
}
|
||||
|
||||
_getTicket() {
|
||||
let filter = {
|
||||
};
|
||||
this.$http.get(`/ticket/api/Tickets/${this.$state.params.id}?filter=${JSON.stringify(filter)}`)
|
||||
.then(res => {
|
||||
if (res.data && res.data.id) {
|
||||
this.$timeout(() => {
|
||||
this.ticket = res.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this._getTicket();
|
||||
}
|
||||
}
|
||||
TicketCard.$inject = ['$http', '$state', '$timeout'];
|
||||
|
||||
ngModule.component('vnTicketCard', {
|
||||
template: require('./ticket-card.html'),
|
||||
controller: TicketCard
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
<mg-ajax path="/item/api/Tickets" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.ticket"
|
||||
form="form"
|
||||
save="post">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium>
|
||||
<div style="max-width: 70em; margin: 0 auto;">
|
||||
<vn-card pad-large>
|
||||
<vn-title>New ticket</vn-title>
|
||||
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Create"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</div>
|
||||
</form>
|
|
@ -0,0 +1,21 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class TicketCreate {
|
||||
constructor($scope, $state) {
|
||||
this.$ = $scope;
|
||||
this.$state = $state;
|
||||
this.Ticket = {};
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.$.watcher.submit().then(
|
||||
json => this.$state.go('ticket.card.data', {id: json.data.id})
|
||||
);
|
||||
}
|
||||
}
|
||||
TicketCreate.$inject = ['$scope', '$state'];
|
||||
|
||||
ngModule.component('vnTicketCreate', {
|
||||
template: require('./ticket-create.html'),
|
||||
controller: TicketCreate
|
||||
});
|
|
@ -1,10 +1,10 @@
|
|||
<a
|
||||
ui-sref="clientCard.basicData({ id: {{::$ctrl.ticket.id}} })"
|
||||
ui-sref="ticket.card.summary({ id: {{::$ctrl.ticket.id}} })"
|
||||
translate-attr="{title: 'View client'}"
|
||||
class="vn-list-item">
|
||||
<vn-horizontal ng-click="$ctrl.onClick($event)">
|
||||
<vn-one>
|
||||
<h6>{{::$ctrl.ticket.name}}</h6>
|
||||
<h6>{{::$ctrl.ticket.nickname}}</h6>
|
||||
<div><vn-label translate>Id</vn-label> {{::$ctrl.ticket.id}}</div>
|
||||
</vn-one>
|
||||
<vn-horizontal class="buttons">
|
|
@ -13,7 +13,7 @@ class Controller {
|
|||
|
||||
ngModule.component('vnTicketItem', {
|
||||
controller: Controller,
|
||||
template: require('./item.html'),
|
||||
template: require('./ticket-item.html'),
|
||||
bindings: {
|
||||
ticket: '<'
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
<mg-ajax path="/client/api/Clients/filter" options="mgIndex"></mg-ajax>
|
||||
<mg-ajax path="/ticket/api/Tickets/filter" options="vnIndexNonAuto"></mg-ajax>
|
||||
<div margin-medium>
|
||||
<div class="vn-list">
|
||||
<vn-card>
|
||||
|
@ -19,6 +19,6 @@
|
|||
<vn-paging index="index" total="index.model.count"></vn-paging>
|
||||
</div>
|
||||
</div>
|
||||
<a ui-sref="create" fixed-bottom-right>
|
||||
<vn-float-button icon="person_add"></vn-float-button>
|
||||
<a ui-sref="ticket.create" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
|
@ -1,5 +1,6 @@
|
|||
import ngModule from '../module';
|
||||
import './item';
|
||||
import './ticket-item';
|
||||
import './style.scss';
|
||||
|
||||
export default class Controller {
|
||||
search(index) {
|
||||
|
@ -8,7 +9,7 @@ export default class Controller {
|
|||
}
|
||||
Controller.$inject = [];
|
||||
|
||||
ngModule.component('vnTicketIndex', {
|
||||
template: require('./index.html'),
|
||||
ngModule.component('vnTicketList', {
|
||||
template: require('./ticket-list.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1 +1,6 @@
|
|||
Tickets: Tickets
|
||||
Notes: Notas
|
||||
Observation type: Tipo de observación
|
||||
Description: Descripción
|
||||
The observation type must be unique: El tipo de observación debe ser único
|
||||
Some fields are invalid: Algunos campos no son válidos
|
|
@ -0,0 +1,60 @@
|
|||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
url="/client/api/Addresses"
|
||||
id-field="id"
|
||||
data="$ctrl.address"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.submit()">
|
||||
<vn-card pad-large>
|
||||
<vn-one margin-medium-top>
|
||||
<vn-title>Notes</vn-title>
|
||||
<mg-ajax path="/ticket/api/ObservationTypes" options="mgIndex as observationTypes"></mg-ajax>
|
||||
<vn-horizontal ng-repeat="ticketObservation in $ctrl.ticketObservations track by $index">
|
||||
<vn-autocomplete
|
||||
ng-if="!ticketObservation.id"
|
||||
vn-one
|
||||
initial-data="ticketObservation.observationType"
|
||||
field="ticketObservation.observationTypeFk"
|
||||
data="observationTypes.model"
|
||||
show-field="description"
|
||||
label="Observation type">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
ng-if="ticketObservation.id"
|
||||
vn-one
|
||||
label="Observation type"
|
||||
model="ticketObservation.observationType.description"
|
||||
disabled="true">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-two
|
||||
margin-large-right
|
||||
label="Description"
|
||||
model="ticketObservation.description">
|
||||
</vn-textfield>
|
||||
<vn-auto pad-medium-top>
|
||||
<vn-icon
|
||||
pointer
|
||||
medium-grey
|
||||
vn-tooltip="Remove note"
|
||||
tooltip-position="left"
|
||||
icon="remove_circle_outline"
|
||||
ng-click="$ctrl.removeObservation($index)">
|
||||
</vn-icon>
|
||||
</vn-auto>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-icon
|
||||
pointer margin-medium-left vn-tooltip="Add note"
|
||||
tooltip-position="right" orange icon="add_circle"
|
||||
ng-if="observationTypes.model.length > $ctrl.ticketObservations.length"
|
||||
ng-click="$ctrl.addObservation()">
|
||||
</vn-icon>
|
||||
</vn-one>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,140 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class TicketObservations {
|
||||
constructor($stateParams, $scope, $http, $translate, vnApp) {
|
||||
this.params = $stateParams;
|
||||
this.$scope = $scope;
|
||||
this.$http = $http;
|
||||
this.$translate = $translate;
|
||||
this.vnApp = vnApp;
|
||||
|
||||
this.ticketObservations = [];
|
||||
this.oldObservations = {};
|
||||
this.removedObservations = [];
|
||||
}
|
||||
|
||||
_setIconAdd() {
|
||||
if (this.ticketObservations.length) {
|
||||
this.ticketObservations.map(element => {
|
||||
element.showAddIcon = false;
|
||||
return true;
|
||||
});
|
||||
this.ticketObservations[this.ticketObservations.length - 1].showAddIcon = true;
|
||||
}
|
||||
}
|
||||
|
||||
_setDirtyForm() {
|
||||
if (this.$scope.form) {
|
||||
this.$scope.form.$setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
_unsetDirtyForm() {
|
||||
if (this.$scope.form) {
|
||||
this.$scope.form.$setPristine();
|
||||
}
|
||||
}
|
||||
|
||||
addObservation() {
|
||||
this.ticketObservations.push({description: null, ticketFk: this.params.id, showAddIcon: true});
|
||||
this._setIconAdd();
|
||||
}
|
||||
|
||||
removeObservation(index) {
|
||||
let item = this.ticketObservations[index];
|
||||
if (item) {
|
||||
this.ticketObservations.splice(index, 1);
|
||||
this._setIconAdd();
|
||||
if (item.id) {
|
||||
this.removedObservations.push(item.id);
|
||||
this._setDirtyForm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_equalObservations(oldObservation, newObservation) {
|
||||
return oldObservation.id === newObservation.id && oldObservation.observationTypeFk === newObservation.observationTypeFk && oldObservation.description === newObservation.description;
|
||||
}
|
||||
|
||||
setOldObservations(response) {
|
||||
this._setIconAdd();
|
||||
response.data.forEach(observation => {
|
||||
this.oldObservations[observation.id] = Object.assign({}, observation);
|
||||
});
|
||||
}
|
||||
|
||||
getObservations() {
|
||||
let filter = {
|
||||
where: {ticketFk: this.params.id},
|
||||
include: ['observationType']
|
||||
};
|
||||
|
||||
this.$http.get(`/ticket/api/TicketObservations?filter=${JSON.stringify(filter)}`).then(response => {
|
||||
this.ticketObservations = response.data;
|
||||
this.setOldObservations(response);
|
||||
});
|
||||
}
|
||||
|
||||
submit() {
|
||||
let typesDefined = [];
|
||||
let repeatedType = false;
|
||||
let canSubmit;
|
||||
let observationsObj = {
|
||||
delete: this.removedObservations,
|
||||
create: [],
|
||||
update: []
|
||||
};
|
||||
|
||||
this.ticketObservations.forEach(observation => {
|
||||
let isNewObservation = !observation.id;
|
||||
|
||||
delete observation.showAddIcon;
|
||||
|
||||
if (typesDefined.indexOf(observation.observationTypeFk) !== -1) {
|
||||
repeatedType = true;
|
||||
return;
|
||||
}
|
||||
typesDefined.push(observation.observationTypeFk);
|
||||
|
||||
if (isNewObservation && observation.description && observation.observationTypeFk) {
|
||||
observationsObj.create.push(observation);
|
||||
}
|
||||
|
||||
if (!isNewObservation && !this._equalObservations(this.oldObservations[observation.id], observation)) {
|
||||
observationsObj.update.push(observation);
|
||||
}
|
||||
});
|
||||
|
||||
if (this.$scope.form.$invalid) {
|
||||
return this.vnApp.showMessage(this.$translate.instant('Some fields are invalid'));
|
||||
}
|
||||
|
||||
if (repeatedType) {
|
||||
return this.vnApp.showMessage(this.$translate.instant('The observation type must be unique'));
|
||||
}
|
||||
|
||||
canSubmit = observationsObj.update.length > 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0;
|
||||
|
||||
if (canSubmit) {
|
||||
return this.$http.post(`/ticket/api/TicketObservations/crudTicketObservations`, observationsObj).then(() => {
|
||||
this.getObservations();
|
||||
this._unsetDirtyForm();
|
||||
});
|
||||
}
|
||||
this.vnApp.showMessage(this.$translate.instant('No changes to save'));
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.getObservations();
|
||||
}
|
||||
}
|
||||
|
||||
TicketObservations.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp'];
|
||||
|
||||
ngModule.component('vnTicketObservations', {
|
||||
template: require('./ticket-observations.html'),
|
||||
controller: TicketObservations,
|
||||
bindings: {
|
||||
ticket: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,143 @@
|
|||
import './ticket-observations.js';
|
||||
|
||||
describe('ticket', () => {
|
||||
describe('Component vnTicketObservations', () => {
|
||||
let $componentController;
|
||||
let $state;
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(() => {
|
||||
angular.mock.module('ticket');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
||||
$componentController = _$componentController_;
|
||||
$state = _$state_;
|
||||
$httpBackend = _$httpBackend_;
|
||||
controller = $componentController('vnTicketObservations', {$state: $state});
|
||||
}));
|
||||
|
||||
describe('add / remove observation', () => {
|
||||
it('should add one empty observation into controller observations collection and call _setIconAdd()', () => {
|
||||
controller.ticketObservations = [];
|
||||
spyOn(controller, '_setIconAdd').and.callThrough();
|
||||
controller.addObservation();
|
||||
|
||||
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
||||
expect(controller.ticketObservations.length).toEqual(1);
|
||||
expect(controller.ticketObservations[0].id).toBe(undefined);
|
||||
expect(controller.ticketObservations[0].showAddIcon).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should remove an observation that occupies the position in the index given and call _setIconAdd()', () => {
|
||||
let index = 2;
|
||||
controller.ticketObservations = [
|
||||
{id: 1, observationTypeFk: 1, description: 'one', showAddIcon: false},
|
||||
{id: 2, observationTypeFk: 2, description: 'two', showAddIcon: false},
|
||||
{id: 3, observationTypeFk: 3, description: 'three', showAddIcon: true}
|
||||
];
|
||||
|
||||
spyOn(controller, '_setIconAdd').and.callThrough();
|
||||
|
||||
controller.removeObservation(index);
|
||||
|
||||
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
||||
expect(controller.ticketObservations.length).toEqual(2);
|
||||
expect(controller.ticketObservations[0].showAddIcon).toBeFalsy();
|
||||
expect(controller.ticketObservations[1].showAddIcon).toBeTruthy();
|
||||
expect(controller.ticketObservations[index]).toBe(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_equalObservations()', () => {
|
||||
it('should return true if two observations are equals independent of control attributes', () => {
|
||||
let observationOne = {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: true};
|
||||
let observationTwo = {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: false};
|
||||
let equals = controller._equalObservations(observationOne, observationTwo);
|
||||
|
||||
expect(equals).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false if two observations aint equals independent of control attributes', () => {
|
||||
let observationOne = {id: 1, observationTypeFk: 1, description: 'one', showAddIcon: true};
|
||||
let observationTwo = {id: 1, observationTypeFk: 1, description: 'two', showAddIcon: true};
|
||||
let equals = controller._equalObservations(observationOne, observationTwo);
|
||||
|
||||
expect(equals).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('get Observations()', () => {
|
||||
it('should perform a GET query to receive the ticket observations', () => {
|
||||
let res = [{id: 1, observationTypeFk: 1, description: 'one'}];
|
||||
|
||||
$httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond(res);
|
||||
$httpBackend.expectGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`);
|
||||
controller.getObservations();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
|
||||
describe('submit()', () => {
|
||||
it("should return an error message 'The observation type must be unique'", () => {
|
||||
controller.$scope.form = {};
|
||||
spyOn(controller.vnApp, 'showMessage').and.callThrough();
|
||||
controller.ticketObservations = [
|
||||
{id: 1, observationTypeFk: 1, description: 'one', itemFk: 1},
|
||||
{observationTypeFk: 1, description: 'one', itemFk: 1}
|
||||
];
|
||||
controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one', itemFk: 1}};
|
||||
controller.submit();
|
||||
|
||||
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The observation type must be unique');
|
||||
});
|
||||
|
||||
it("should perfom a query to delete observations", () => {
|
||||
controller.$scope.form = {$setPristine: () => {}};
|
||||
controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one'}};
|
||||
controller.ticketObservations = [];
|
||||
controller.removedObservations = [1];
|
||||
|
||||
$httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond([]);
|
||||
$httpBackend.expectPOST(`/ticket/api/TicketObservations/crudTicketObservations`).respond('ok!');
|
||||
controller.submit();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it("should perfom a query to update observations", () => {
|
||||
controller.$scope.form = {$setPristine: () => {}};
|
||||
controller.ticketObservations = [{id: 1, observationTypeFk: 1, description: 'number one!'}];
|
||||
controller.oldObservations = {1: {id: 1, observationTypeFk: 1, description: 'one'}};
|
||||
|
||||
$httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond([]);
|
||||
$httpBackend.expectPOST(`/ticket/api/TicketObservations/crudTicketObservations`).respond('ok!');
|
||||
controller.submit();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it("should perfom a query to create new observation", () => {
|
||||
controller.$scope.form = {$setPristine: () => {}};
|
||||
controller.ticketObservations = [{observationTypeFk: 2, description: 'two'}];
|
||||
|
||||
$httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond([]);
|
||||
$httpBackend.expectPOST(`/ticket/api/TicketObservations/crudTicketObservations`).respond('ok!');
|
||||
controller.submit();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
|
||||
it("should return a message 'No changes to save' when there are no changes to apply", () => {
|
||||
controller.$scope.form = {$setPristine: () => {}};
|
||||
spyOn(controller.vnApp, 'showMessage').and.callThrough();
|
||||
controller.oldObservations = [
|
||||
{id: 1, observationTypeFk: 1, description: 'one', showAddIcon: false},
|
||||
{id: 2, observationTypeFk: 2, description: 'two', showAddIcon: true}
|
||||
];
|
||||
controller.ticketObservations = [];
|
||||
controller.submit();
|
||||
|
||||
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No changes to save');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,56 @@
|
|||
<mg-ajax
|
||||
path="/ticket/api/Tickets/{{index.params.id}}/packages"
|
||||
options="mgIndex">
|
||||
</mg-ajax>
|
||||
|
||||
<vn-card pad-large>
|
||||
<vn-title>Packages</vn-title>
|
||||
<vn-one>
|
||||
<vn-horizontal ng-repeat="package in index.model track by package.id">
|
||||
<vn-autocomplete vn-one
|
||||
margin-large-right
|
||||
url="/ticket/api/Packagings/listPackaging"
|
||||
label="Package"
|
||||
show-field="name"
|
||||
value-field="packagingFk"
|
||||
field="package.packagingFk">
|
||||
<tpl-item>{{id}} : {{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
margin-large-right
|
||||
label="Quantity"
|
||||
model="package.quantity">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
margin-large-right
|
||||
label="Added"
|
||||
model="package.created | date: 'dd/MM/yyyy'"
|
||||
disabled="true"
|
||||
ng-readonly="true">
|
||||
</vn-textfield>
|
||||
<vn-auto pad-medium-top>
|
||||
<vn-icon
|
||||
pointer
|
||||
medium-grey
|
||||
vn-tooltip="Remove package"
|
||||
tooltip-position = "left"
|
||||
icon="remove_circle_outline"
|
||||
ng-click="$ctrl.removePackage($index)">
|
||||
</vn-icon>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-icon
|
||||
pointer
|
||||
margin-medium-left
|
||||
vn-tooltip="Add package"
|
||||
tooltip-position = "right"
|
||||
orange
|
||||
icon="add_circle"
|
||||
ng-click="$ctrl.addPackage()">
|
||||
</vn-icon>
|
||||
</vn-one>
|
||||
</vn-card>
|
|
@ -0,0 +1,19 @@
|
|||
import ngModule from '../../module';
|
||||
|
||||
class Controller {
|
||||
|
||||
construct($http, $scope) {
|
||||
this.$http = $http;
|
||||
this.$ = $scope;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$http', '$scope'];
|
||||
|
||||
ngModule.component('vnTicketPackageList', {
|
||||
template: require('./package-list.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
ticket: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,6 @@
|
|||
Packages: Embalajes
|
||||
Package: Embalaje
|
||||
Quantity: Cantidad
|
||||
Added: Añadido
|
||||
Add package: Añadir embalaje
|
||||
Remove package: Quitar embalaje
|
|
@ -0,0 +1,4 @@
|
|||
date : Fecha
|
||||
Employee : Empleado
|
||||
State: Estado
|
||||
Review: Revision
|
|
@ -0,0 +1,23 @@
|
|||
<mg-ajax path="" options="vnIndexNonAuto"></mg-ajax>
|
||||
<vn-vertical pad-medium>
|
||||
<vn-card pad-large>
|
||||
<vn-vertical>
|
||||
<vn-title>Review</vn-title>
|
||||
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
|
||||
<vn-column-header vn-one pad-medium-h field="date" text="date"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="employee" text="Employee" default-order="ASC"></vn-column-header>
|
||||
<vn-column-header vn-two pad-medium-h field="state" text="State" order-locked></vn-column-header>
|
||||
</vn-grid-header>
|
||||
<vn-one class="list list-content">
|
||||
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one class="text-center pad-small-v" ng-if="index.model.count === 0" translate>No results</vn-one>
|
||||
<vn-horizontal vn-one class="list list-footer"></vn-horizontal>
|
||||
<vn-paging vn-one margin-large-top index="index" total="index.model.count"></vn-paging>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
<a ui-sref="clientCard.ticket.create" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
|
@ -0,0 +1,18 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class ticketReview {
|
||||
construct($http, $scope) {
|
||||
this.$http = $http;
|
||||
this.$ = $scope;
|
||||
}
|
||||
}
|
||||
|
||||
ticketReview.$inject = ['$http', '$scope'];
|
||||
|
||||
ngModule.component('vnTicketReview', {
|
||||
template: require('./review.html'),
|
||||
controller: ticketReview,
|
||||
bindings: {
|
||||
ticket: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,9 @@
|
|||
<vn-card class="summary">
|
||||
<vn-vertical pad-medium>
|
||||
<vn-auto>
|
||||
<h5 text-center pad-small-v class="tittle">Ticket Summary</h5>
|
||||
</vn-auto>
|
||||
<vn-horizontal>
|
||||
</vn-horizontal>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
|
@ -0,0 +1,12 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class TicketSummary {}
|
||||
TicketSummary.$inject = [];
|
||||
|
||||
ngModule.component('vnTicketSummary', {
|
||||
template: require('./ticket-summary.html'),
|
||||
controller: TicketSummary,
|
||||
bindings: {
|
||||
ticket: '<'
|
||||
}
|
||||
});
|
|
@ -1,4 +1,10 @@
|
|||
export * from './module';
|
||||
|
||||
import './index/index';
|
||||
|
||||
import './list/ticket-list';
|
||||
import './create/ticket-create';
|
||||
import './card/ticket-card';
|
||||
import './summary/ticket-summary';
|
||||
import './data/ticket-data';
|
||||
import './notes/ticket-observations';
|
||||
import './package/list/package-list';
|
||||
import './review/review';
|
||||
|
|
|
@ -11,7 +11,8 @@ export default {
|
|||
},
|
||||
moduleAccessView: {
|
||||
clientsSectionButton: `${components.vnModuleContainer}[ui-sref="clients"]`,
|
||||
itemsSectionButton: `${components.vnModuleContainer}[ui-sref="item.index"]`
|
||||
itemsSectionButton: `${components.vnModuleContainer}[ui-sref="item.index"]`,
|
||||
ticketsSectionButton: `${components.vnModuleContainer}[ui-sref="ticket.list"]`
|
||||
},
|
||||
clientsIndex: {
|
||||
searchClientInput: `${components.vnTextfield}`,
|
||||
|
@ -188,24 +189,29 @@ export default {
|
|||
itemTags: {
|
||||
goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
|
||||
tagsButton: `${components.vnMenuItem}[ui-sref="item.card.tags"]`,
|
||||
firstRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnIcon}[icon="remove_circle_outline"]`,
|
||||
firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
|
||||
firstTagDisabled: `vn-item-tags vn-horizontal:nth-child(2) > vn-textfield[label="Tag"] > div > input`,
|
||||
firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||
firstValueInput: `vn-item-tags vn-horizontal:nth-child(2) > vn-textfield[label="Value"] > div > input`,
|
||||
firstRelevancyInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Relevancy"] > div > input`,
|
||||
secondTagSelect: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
|
||||
secondTagDisabled: `vn-item-tags vn-horizontal:nth-child(3) > vn-textfield[label="Tag"] > div > input`,
|
||||
secondTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||
secondValueInput: `vn-item-tags vn-horizontal:nth-child(3) > vn-textfield[label="Value"] > div > input`,
|
||||
secondRelevancyInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Relevancy"] > div > input`,
|
||||
thirdTagSelect: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
|
||||
thirdTagDisabled: `vn-item-tags vn-horizontal:nth-child(4) > vn-textfield[label="Tag"] > div > input`,
|
||||
thirdTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||
thirdValueInput: `vn-item-tags vn-horizontal:nth-child(4) > vn-textfield[label="Value"] > div > input`,
|
||||
thirdRelevancyInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Relevancy"] > div > input`,
|
||||
fourthTagSelect: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
|
||||
fourthTagDisabled: `vn-item-tags vn-horizontal:nth-child(5) > vn-textfield[label="Tag"] > div > input`,
|
||||
fourthTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||
fourthValueInput: `vn-item-tags vn-horizontal:nth-child(5) > vn-textfield[label="Value"] > div > input`,
|
||||
fourthRelevancyInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Relevancy"] > div > input`,
|
||||
fifthRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnIcon}[icon="remove_circle_outline"]`,
|
||||
fifthTagSelect: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
|
||||
fifthTagDisabled: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Tag"] > div > input`,
|
||||
fifthTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(5)`,
|
||||
fifthValueInput: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Value"] > div > input`,
|
||||
fifthRelevancyInput: `vn-horizontal:nth-child(6) > vn-textfield[label="Relevancy"] > div > input`,
|
||||
|
@ -233,14 +239,17 @@ export default {
|
|||
nicheButton: `${components.vnMenuItem}[ui-sref="item.card.niche"]`,
|
||||
addNicheButton: `${components.vnIcon}[icon="add_circle"]`,
|
||||
firstWarehouseSelect: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
|
||||
firstWarehouseDisabled: `vn-horizontal:nth-child(2) > vn-textfield[label="Warehouse"] > div > input`,
|
||||
firstWarehouseSelectSecondOption: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||
firstCodeInput: `vn-horizontal:nth-child(2) > vn-textfield[label="code"] > div > input`,
|
||||
secondWarehouseSelect: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
|
||||
thirdWarehouseSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
|
||||
thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`,
|
||||
secondWarehouseDisabled: `vn-horizontal:nth-child(3) > vn-textfield[label="Warehouse"] > div > input`,
|
||||
secondCodeInput: `vn-horizontal:nth-child(3) > vn-textfield[label="code"] > div > input`,
|
||||
secondNicheRemoveButton: `vn-horizontal:nth-child(3) > vn-one > ${components.vnIcon}[icon="remove_circle_outline"]`,
|
||||
firstCodeInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`,
|
||||
secondCodeInput: `vn-horizontal:nth-child(3) > ${components.vnTextfield}`,
|
||||
thirdCodeInput: `vn-horizontal:nth-child(4) > ${components.vnTextfield}`,
|
||||
thirdWarehouseSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
|
||||
thirdWarehouseDisabled: `vn-horizontal:nth-child(4) > vn-textfield[label="Warehouse"] > div > input`,
|
||||
thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`,
|
||||
thirdCodeInput: `vn-horizontal:nth-child(4) > vn-textfield[label="code"] > div > input`,
|
||||
submitNichesButton: `${components.vnSubmit}`
|
||||
},
|
||||
itemBotanical: {
|
||||
|
@ -261,5 +270,25 @@ export default {
|
|||
niche: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(2) > vn-vertical > p:nth-child(2)`,
|
||||
botanical: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(3) > vn-vertical > p`,
|
||||
barcode: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(4) > vn-vertical > p`
|
||||
},
|
||||
ticketsIndex: {
|
||||
createTicketButton: `${components.vnFloatButton}`,
|
||||
searchResult: `vn-ticket-item a`,
|
||||
searchTicketInput: `${components.vnTextfield}`,
|
||||
searchButton: `${components.vnSearchBar} > vn-icon-button > button`
|
||||
},
|
||||
ticketNotes: {
|
||||
notesButton: `${components.vnMenuItem}[ui-sref="ticket.card.observations"]`,
|
||||
firstNoteRemoveButton: `${components.vnIcon}[icon="remove_circle_outline"]`,
|
||||
addNoteButton: `${components.vnIcon}[icon="add_circle"]`,
|
||||
firstNoteSelect: `${components.vnAutocomplete}[field="ticketObservation.observationTypeFk"] input`,
|
||||
firstNoteSelectSecondOption: `${components.vnAutocomplete}[field="ticketObservation.observationTypeFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||
firstNoteDisabled: `vn-textfield[label="Observation type"] > div > input`,
|
||||
firstDescriptionInput: `vn-textfield[label="Description"] > div > input`,
|
||||
submitNotesButton: `${components.vnSubmit}`
|
||||
},
|
||||
ticketPackages: {
|
||||
packagesButton: `${components.vnMenuItem}[ui-sref="ticket.card.package.list"]`,
|
||||
firstPackageSelect: `${components.vnAutocomplete}[label="Package"] input`
|
||||
}
|
||||
};
|
||||
|
|
|
@ -61,7 +61,7 @@ describe('lock verified data path', () => {
|
|||
.wait(selectors.clientFiscalData.verifiedDataCheckboxInput)
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).className;
|
||||
}, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(3) > label')
|
||||
}, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(4) > label')
|
||||
.then(result => {
|
||||
expect(result).toContain('is-disabled');
|
||||
});
|
||||
|
@ -452,7 +452,7 @@ describe('lock verified data path', () => {
|
|||
.wait(selectors.clientFiscalData.verifiedDataCheckboxInput)
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).className;
|
||||
}, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(3) > label')
|
||||
}, 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > form > vn-card > div > vn-horizontal:nth-child(5) > vn-check:nth-child(4) > label')
|
||||
.then(result => {
|
||||
expect(result).toContain('is-disabled');
|
||||
});
|
||||
|
|
|
@ -66,9 +66,10 @@ describe('edit item basic data path', () => {
|
|||
|
||||
it(`should confirm the item name was edited`, () => {
|
||||
return nightmare
|
||||
.click(selectors.itemNiches.firstCodeInput)
|
||||
.wait(selectors.itemNiches.firstCodeInput)
|
||||
.click(selectors.itemNiches.nicheButton)
|
||||
.wait(selectors.itemNiches.firstWarehouseDisabled)
|
||||
.waitToClick(selectors.itemBasicData.basicDataButton)
|
||||
.waitForTextInInput(selectors.itemBasicData.nameInput, 'Rose of Purity')
|
||||
.getInputValue(selectors.itemBasicData.nameInput)
|
||||
.then(result => {
|
||||
expect(result).toEqual('Rose of Purity');
|
||||
|
|
|
@ -61,7 +61,7 @@ describe('add item tax path', () => {
|
|||
it(`should confirm the item tax class was edited`, () => {
|
||||
return nightmare
|
||||
.click(selectors.itemTags.tagsButton)
|
||||
.wait(selectors.itemTags.firstTagSelect)
|
||||
.wait(selectors.itemTags.firstTagDisabled)
|
||||
.waitToClick(selectors.itemTax.taxButton)
|
||||
.waitForTextInInput(selectors.itemTax.firstClassSelect, 'general')
|
||||
.getInputValue(selectors.itemTax.firstClassSelect)
|
||||
|
|
|
@ -43,22 +43,14 @@ describe('create item tags path', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it(`should create a new tag, edit another and delete a former one`, () => {
|
||||
it(`should create a new tag and delete a former one`, () => {
|
||||
return nightmare
|
||||
.waitToClick(selectors.itemTags.firstTagSelect)
|
||||
.waitToClick(selectors.itemTags.firstTagSelectOptionOne)
|
||||
.clearInput(selectors.itemTags.firstValueInput)
|
||||
.type(selectors.itemTags.firstValueInput, 'Dark Blue')
|
||||
.clearInput(selectors.itemTags.firstRelevancyInput)
|
||||
.type(selectors.itemTags.firstRelevancyInput, '2')
|
||||
.waitToClick(selectors.itemTags.fifthRemoveTagButton)
|
||||
.waitToClick(selectors.itemTags.firstRemoveTagButton)
|
||||
.waitToClick(selectors.itemTags.addItemTagButton)
|
||||
.waitToClick(selectors.itemTags.fifthTagSelect)
|
||||
.waitToClick(selectors.itemTags.fifthTagSelectOptionFive)
|
||||
.type(selectors.itemTags.fifthValueInput, 'Thanos')
|
||||
.type(selectors.itemTags.fifthRelevancyInput, '1')
|
||||
.clearInput(selectors.itemTags.secondRelevancyInput)
|
||||
.type(selectors.itemTags.secondRelevancyInput, '5')
|
||||
.click(selectors.itemTags.submitItemTagsButton)
|
||||
.waitForSnackbar()
|
||||
.then(result => {
|
||||
|
@ -71,8 +63,8 @@ describe('create item tags path', () => {
|
|||
.click(selectors.itemBasicData.basicDataButton)
|
||||
.wait(selectors.itemBasicData.nameInput)
|
||||
.click(selectors.itemTags.tagsButton)
|
||||
.waitForTextInInput(selectors.itemTags.firstTagSelect, 'Owner')
|
||||
.getInputValue(selectors.itemTags.firstTagSelect)
|
||||
.waitForTextInInput(selectors.itemTags.firstTagDisabled, 'Owner')
|
||||
.getInputValue(selectors.itemTags.firstTagDisabled)
|
||||
.then(result => {
|
||||
expect(result).toEqual('Owner');
|
||||
});
|
||||
|
@ -98,19 +90,19 @@ describe('create item tags path', () => {
|
|||
|
||||
it(`should confirm the second select is the expected one`, () => {
|
||||
return nightmare
|
||||
.waitForTextInInput(selectors.itemTags.secondTagSelect, 'Color')
|
||||
.getInputValue(selectors.itemTags.secondTagSelect)
|
||||
.waitForTextInInput(selectors.itemTags.secondTagDisabled, 'Location')
|
||||
.getInputValue(selectors.itemTags.secondTagDisabled)
|
||||
.then(result => {
|
||||
expect(result).toEqual('Color');
|
||||
expect(result).toEqual('Location');
|
||||
});
|
||||
});
|
||||
|
||||
it(`should confirm the second value is the expected one`, () => {
|
||||
return nightmare
|
||||
.waitForTextInInput(selectors.itemTags.secondValueInput, 'Dark Blue')
|
||||
.waitForTextInInput(selectors.itemTags.secondValueInput, 'Gamoras hideout')
|
||||
.getInputValue(selectors.itemTags.secondValueInput)
|
||||
.then(result => {
|
||||
expect(result).toEqual('Dark Blue');
|
||||
expect(result).toEqual('Gamoras hideout');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -125,8 +117,8 @@ describe('create item tags path', () => {
|
|||
|
||||
it(`should confirm the third select is the expected one`, () => {
|
||||
return nightmare
|
||||
.waitForTextInInput(selectors.itemTags.thirdTagSelect, 'Shape')
|
||||
.getInputValue(selectors.itemTags.thirdTagSelect)
|
||||
.waitForTextInInput(selectors.itemTags.thirdTagDisabled, 'Shape')
|
||||
.getInputValue(selectors.itemTags.thirdTagDisabled)
|
||||
.then(result => {
|
||||
expect(result).toEqual('Shape');
|
||||
});
|
||||
|
@ -152,8 +144,8 @@ describe('create item tags path', () => {
|
|||
|
||||
it(`should confirm the fourth select is the expected one`, () => {
|
||||
return nightmare
|
||||
.waitForTextInInput(selectors.itemTags.fourthTagSelect, 'Power')
|
||||
.getInputValue(selectors.itemTags.fourthTagSelect)
|
||||
.waitForTextInInput(selectors.itemTags.fourthTagDisabled, 'Power')
|
||||
.getInputValue(selectors.itemTags.fourthTagDisabled)
|
||||
.then(result => {
|
||||
expect(result).toEqual('Power');
|
||||
});
|
||||
|
@ -179,19 +171,19 @@ describe('create item tags path', () => {
|
|||
|
||||
it(`should confirm the fifth select is the expected one`, () => {
|
||||
return nightmare
|
||||
.waitForTextInInput(selectors.itemTags.fifthTagSelect, 'Location')
|
||||
.getInputValue(selectors.itemTags.fifthTagSelect)
|
||||
.waitForTextInInput(selectors.itemTags.fifthTagDisabled, 'Color')
|
||||
.getInputValue(selectors.itemTags.fifthTagDisabled)
|
||||
.then(result => {
|
||||
expect(result).toEqual('Location');
|
||||
expect(result).toEqual('Color');
|
||||
});
|
||||
});
|
||||
|
||||
it(`should confirm the fifth value is the expected one`, () => {
|
||||
return nightmare
|
||||
.waitForTextInInput(selectors.itemTags.fifthValueInput, 'Gamoras hideout')
|
||||
.waitForTextInInput(selectors.itemTags.fifthValueInput, 'Yellow')
|
||||
.getInputValue(selectors.itemTags.fifthValueInput)
|
||||
.then(result => {
|
||||
expect(result).toEqual('Gamoras hideout');
|
||||
expect(result).toEqual('Yellow');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -43,13 +43,9 @@ describe('create item niche path', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it(`should click create a new niche, edit another and delete a former one`, () => {
|
||||
it(`should click create a new niche and delete a former one`, () => {
|
||||
return nightmare
|
||||
.waitToClick(selectors.itemNiches.addNicheButton)
|
||||
.waitToClick(selectors.itemNiches.firstWarehouseSelect)
|
||||
.waitToClick(selectors.itemNiches.firstWarehouseSelectSecondOption)
|
||||
.clearInput(selectors.itemNiches.firstCodeInput)
|
||||
.type(selectors.itemNiches.firstCodeInput, 'A2')
|
||||
.waitToClick(selectors.itemNiches.secondNicheRemoveButton)
|
||||
.waitToClick(selectors.itemNiches.thirdWarehouseSelect)
|
||||
.waitToClick(selectors.itemNiches.thirdWarehouseSelectFourthOption)
|
||||
|
@ -66,21 +62,21 @@ describe('create item niche path', () => {
|
|||
.click(selectors.itemBasicData.basicDataButton)
|
||||
.wait(selectors.itemBasicData.nameInput)
|
||||
.click(selectors.itemNiches.nicheButton)
|
||||
.waitForTextInInput(selectors.itemNiches.firstWarehouseSelect, 'Warehouse Two')
|
||||
.getInputValue(selectors.itemNiches.firstWarehouseSelect)
|
||||
.waitForTextInInput(selectors.itemNiches.firstWarehouseDisabled, 'Warehouse One')
|
||||
.getInputValue(selectors.itemNiches.firstWarehouseDisabled)
|
||||
.then(result => {
|
||||
expect(result).toEqual('Warehouse Two');
|
||||
expect(result).toEqual('Warehouse One');
|
||||
return nightmare
|
||||
.getInputValue(selectors.itemNiches.firstCodeInput);
|
||||
})
|
||||
.then(result => {
|
||||
expect(result).toEqual('A2');
|
||||
expect(result).toEqual('A1');
|
||||
});
|
||||
});
|
||||
|
||||
it(`should confirm the second niche is the expected one`, () => {
|
||||
return nightmare
|
||||
.getInputValue(selectors.itemNiches.secondWarehouseSelect)
|
||||
.getInputValue(selectors.itemNiches.secondWarehouseDisabled)
|
||||
.then(result => {
|
||||
expect(result).toEqual('Warehouse Three');
|
||||
return nightmare
|
||||
|
@ -93,7 +89,7 @@ describe('create item niche path', () => {
|
|||
|
||||
it(`should confirm the third niche is the expected one`, () => {
|
||||
return nightmare
|
||||
.getInputValue(selectors.itemNiches.thirdWarehouseSelect)
|
||||
.getInputValue(selectors.itemNiches.thirdWarehouseDisabled)
|
||||
.then(result => {
|
||||
expect(result).toEqual('Warehouse Four');
|
||||
return nightmare
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import createNightmare from '../../helpers/helpers';
|
||||
|
||||
describe('create item niche path', () => {
|
||||
const nightmare = createNightmare();
|
||||
|
||||
beforeAll(() => {
|
||||
return nightmare
|
||||
.waitForLogin('developer');
|
||||
});
|
||||
|
||||
it('should access to the tickets index by clicking the tickets button', () => {
|
||||
return nightmare
|
||||
.click(selectors.moduleAccessView.ticketsSectionButton)
|
||||
.wait(selectors.ticketsIndex.createTicketButton)
|
||||
.parsedUrl()
|
||||
.then(url => {
|
||||
expect(url.hash).toEqual('#!/ticket/list');
|
||||
});
|
||||
});
|
||||
|
||||
it('should search for the ticket with id 1', () => {
|
||||
return nightmare
|
||||
.wait(selectors.ticketsIndex.searchTicketInput)
|
||||
.type(selectors.ticketsIndex.searchTicketInput, '1')
|
||||
.click(selectors.ticketsIndex.searchButton)
|
||||
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||
.countSearchResults(selectors.ticketsIndex.searchResult)
|
||||
.then(result => {
|
||||
expect(result).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
it(`should click on the search result to access to the ticket notes`, () => {
|
||||
return nightmare
|
||||
.waitForTextInElement(selectors.ticketsIndex.searchResult, '1')
|
||||
.waitToClick(selectors.ticketsIndex.searchResult)
|
||||
.waitToClick(selectors.ticketNotes.notesButton)
|
||||
.waitForURL('observations')
|
||||
.url()
|
||||
.then(url => {
|
||||
expect(url).toContain('observations');
|
||||
});
|
||||
});
|
||||
|
||||
it(`should click create a new note and delete a former one`, () => {
|
||||
return nightmare
|
||||
.waitToClick(selectors.ticketNotes.firstNoteRemoveButton)
|
||||
.waitToClick(selectors.ticketNotes.addNoteButton)
|
||||
.waitToClick(selectors.ticketNotes.firstNoteSelect)
|
||||
.waitForTextInElement(selectors.ticketNotes.firstNoteSelectSecondOption, 'observation two')
|
||||
.waitToClick(selectors.ticketNotes.firstNoteSelectSecondOption)
|
||||
.type(selectors.ticketNotes.firstDescriptionInput, 'description')
|
||||
.click(selectors.ticketNotes.submitNotesButton)
|
||||
.waitForSnackbar()
|
||||
.then(result => {
|
||||
expect(result).toContain('Data saved!');
|
||||
});
|
||||
});
|
||||
|
||||
it(`should confirm the note is the expected one`, () => {
|
||||
return nightmare
|
||||
.click(selectors.ticketPackages.packagesButton)
|
||||
.wait(selectors.ticketPackages.firstPackageSelect)
|
||||
.click(selectors.ticketNotes.notesButton)
|
||||
.waitForTextInInput(selectors.ticketNotes.firstNoteDisabled, 'observation two')
|
||||
.getInputValue(selectors.ticketNotes.firstNoteDisabled)
|
||||
.then(result => {
|
||||
expect(result).toEqual('observation two');
|
||||
return nightmare
|
||||
.getInputValue(selectors.ticketNotes.firstDescriptionInput);
|
||||
})
|
||||
.then(result => {
|
||||
expect(result).toEqual('description');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -105,7 +105,7 @@
|
|||
"angular": {
|
||||
"version": "1.6.8",
|
||||
"resolved": "https://registry.npmjs.org/angular/-/angular-1.6.8.tgz",
|
||||
"integrity": "sha1-W+N4pYvpGlSJ54tZxFGM2f0nP/s="
|
||||
"integrity": "sha512-9WErZIOw1Cu1V5Yxdvxz/6YpND8ntdP71fdPpufPFJvZodZXqCjQBYrHqEoMZreO5i84O3D/Jw/vepoFt68Azw=="
|
||||
},
|
||||
"angular-cookies": {
|
||||
"version": "1.6.4",
|
||||
|
@ -8375,6 +8375,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"gulp-env": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/gulp-env/-/gulp-env-0.4.0.tgz",
|
||||
"integrity": "sha1-g3BkaUmjJJPcBtrZSgZDKW+q2+g=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ini": "1.3.4",
|
||||
"through2": "2.0.1"
|
||||
}
|
||||
},
|
||||
"gulp-extend": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gulp-extend/-/gulp-extend-0.2.0.tgz",
|
||||
|
@ -10985,7 +10995,7 @@
|
|||
"karma-firefox-launcher": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-1.1.0.tgz",
|
||||
"integrity": "sha1-LEcDBFLwRTHrfRPU/HZpYwu5Mzk=",
|
||||
"integrity": "sha512-LbZ5/XlIXLeQ3cqnCbYLn+rOVhuMIK9aZwlP6eOLGzWdo1UVp7t6CN3DP4SafiRLjexKwHeKHDm0c38Mtd3VxA==",
|
||||
"dev": true
|
||||
},
|
||||
"karma-jasmine": {
|
||||
|
@ -11006,7 +11016,7 @@
|
|||
"karma-webpack": {
|
||||
"version": "2.0.9",
|
||||
"resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-2.0.9.tgz",
|
||||
"integrity": "sha1-YciAkffdkQY1E0wDKyZqRlr/tX8=",
|
||||
"integrity": "sha512-F1j3IG/XhiMzcunAXbWXH95uizjzr3WdTzmVWlta8xqxcCtAu9FByCb4sccIMxaVFAefpgnUW9KlCo0oLvIX6A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "0.9.2",
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
module.exports = Self => {
|
||||
Self.installMethod('filter', filterParams);
|
||||
|
||||
function filterParams(params) {
|
||||
return {
|
||||
where: {
|
||||
creditClassification: params.creditClassification
|
||||
},
|
||||
skip: (params.page - 1) * params.size,
|
||||
limit: params.size,
|
||||
order: params.order
|
||||
};
|
||||
}
|
||||
};
|
|
@ -33,7 +33,7 @@
|
|||
"model": "Client",
|
||||
"foreignKey": "client"
|
||||
},
|
||||
"creditInsurance": {
|
||||
"creditInsurances": {
|
||||
"type": "hasMany",
|
||||
"model": "CreditInsurance",
|
||||
"foreignKey": "creditClassification"
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
module.exports = function(Self) {
|
||||
require('../methods/creditInsurance/filter.js')(Self);
|
||||
|
||||
Self.validateBinded('credit', Self.validateCredit, {
|
||||
message: 'The credit must be an integer greater than or equal to zero',
|
||||
allowNull: false, // FIXME: Ignored by loopback when it's false
|
||||
allowBlank: false
|
||||
});
|
||||
|
||||
Self.validateCredit = function(credit) {
|
||||
return (credit >= 0 && credit % 1 == 0);
|
||||
};
|
||||
|
||||
Self.validateBinded('grade', Self.validateGrade, {
|
||||
message: 'The grade must be an integer greater than or equal to zero',
|
||||
allowNull: true
|
||||
});
|
||||
|
||||
Self.validateGrade = function(grade) {
|
||||
return (typeof grade === 'undefined' || (grade >= 0 && grade % 1 == 0));
|
||||
};
|
||||
};
|
|
@ -27,7 +27,7 @@
|
|||
}
|
||||
},
|
||||
"relations": {
|
||||
"creditClassification": {
|
||||
"classification": {
|
||||
"type": "belongsTo",
|
||||
"model": "CreditClassification",
|
||||
"foreignKey": "creditClassification"
|
||||
|
|
|
@ -397,6 +397,12 @@ INSERT INTO `vn`.`item`(`id`, `name`,`typeFk`,`size`,`inkFk`,`category`,`stems`,
|
|||
(4, 'Mark I', 1, 60, 'AMR', 'EXT', 1, 1, 'Iron Mans first armor', 1, 05080000, 1, 2, 0, NULL, 0, 66090, 2),
|
||||
(5, 'Mjolnir', 3, 30, 'AZR', 'EXT', 1, 2, 'Thors hammer!', 2, 06021010, 1, 2, 0, NULL, 0, 67350, 2);
|
||||
|
||||
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `checked`, `workerFk`)
|
||||
VALUES
|
||||
( 1, 1, 1, 0, CURDATE(), 1, 0, 2, 1),
|
||||
( 2, 1, 1, 1, CURDATE(), 2, 1, 0, 2),
|
||||
( 3, 2, 2, 2, CURDATE(), 3, 2, 0, NULL);
|
||||
|
||||
INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPackageReturnable`, `created`, `itemFk`, `price`)
|
||||
VALUES
|
||||
(1, 0.00, 10, 10, 0, 0, CURDATE(), 1, 1.50),
|
||||
|
@ -415,6 +421,29 @@ INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `pric
|
|||
( 2, 1, 1, 'Gem of Time', 2 , 1.5, 0, 0, 0, CURDATE()),
|
||||
( 3, 2, 2, 'Mjolnir' , 10, 4 , 0, 0, 0, CURDATE());
|
||||
|
||||
INSERT INTO `vn`.`saleChecked`(`saleFk`, `isChecked`)
|
||||
VALUES
|
||||
( 1, 0),
|
||||
( 2, 1);
|
||||
|
||||
INSERT INTO `vn`.`componentTypeRate`(`id`, `type`)
|
||||
VALUES
|
||||
( 1, 'agency'),
|
||||
( 2, 'client'),
|
||||
( 3, 'company');
|
||||
|
||||
INSERT INTO `vn`.`componentRate`(`id`, `name`, `componentTypeRate`, `classRate`, `tax`, `isRenewable`)
|
||||
VALUES
|
||||
( 1, 'Special price', 1, NULL, NULL, 1),
|
||||
( 2, 'Delivery', 2, NULL, NULL, 1),
|
||||
( 3, 'Mana', 3, 1, NULL, 0 );
|
||||
|
||||
INSERT INTO `vn`.`saleComponent`(`saleFk`, `componentFk`, `value`)
|
||||
VALUES
|
||||
( 1, 1, 0.5),
|
||||
( 2, 2, 1.2 );
|
||||
|
||||
|
||||
INSERT INTO `vn`.`itemBarcode`(`id`, `itemFk`, `code`)
|
||||
VALUES
|
||||
(1, 1 ,1 ),
|
||||
|
|
|
@ -7,3 +7,8 @@ INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `pri
|
|||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('TicketPackaging', '*', '*', 'ALLOW', 'ROLE', 'employee');
|
||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Packaging', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Packaging', '*', 'WRITE', 'ALLOW', 'ROLE', 'logistic');
|
||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('SaleChecked', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('SaleComponent', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Expedition', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Expedition', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Expedition', '*', 'WRITE', 'ALLOW', 'ROLE', 'production');
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
USE `vn`;
|
||||
CREATE
|
||||
OR REPLACE ALGORITHM = UNDEFINED
|
||||
DEFINER = `root`@`%`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `vn`.`saleChecked` AS
|
||||
SELECT
|
||||
`m`.`Id_Movimiento` AS `saleFk`,
|
||||
`m`.`checked` AS `isChecked`
|
||||
FROM
|
||||
`vn2008`.`Movimientos_checked` `m`;
|
|
@ -0,0 +1,30 @@
|
|||
USE `vn`;
|
||||
DROP procedure IF EXISTS `ticketVolume`;
|
||||
|
||||
DELIMITER $$
|
||||
USE `vn`$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`ticketVolume`(IN vTicketId INT)
|
||||
BEGIN
|
||||
DECLARE vWarehouseId INTEGER;
|
||||
DECLARE vShippedDate DATE;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS ticketVolume;
|
||||
SELECT warehouseFk, shipped INTO vWarehouseId,vShippedDate FROM vn.ticket WHERE id = vTicketId;
|
||||
|
||||
CREATE TEMPORARY TABLE IF NOT EXISTS ticketVolume ENGINE MEMORY
|
||||
|
||||
SELECT itemFk,quantity, concept, VolUd as m3_uni, volume as m3, @m3:= @m3 + ifnull(volume,0) as m3_total
|
||||
FROM
|
||||
(
|
||||
SELECT round(r.cm3 / 1000000,3) as VolUd ,s.quantity, round(r.cm3 * s.quantity / 1000000,3) as volume,
|
||||
s.itemFk, s.concept, @m3:= 0, @vol:=0, t.agencyModeFk
|
||||
FROM sale s
|
||||
JOIN vn.ticket t on t.id = s.ticketFk
|
||||
JOIN bi.rotacion r ON r.Id_Article = s.itemFk AND r.warehouse_id = t.warehouseFk
|
||||
WHERE s.ticketFk = vTicketId
|
||||
) sub;
|
||||
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
USE `vn`;
|
||||
CREATE
|
||||
OR REPLACE ALGORITHM = UNDEFINED
|
||||
DEFINER = `root`@`%`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `vn`.`expedition` AS
|
||||
SELECT
|
||||
`e`.`expeditions_id` AS `id`,
|
||||
`e`.`agency_id` AS `agencyModeFk`,
|
||||
`e`.`ticket_id` AS `ticketFk`,
|
||||
`e`.`EsBulto` AS `isBox`,
|
||||
`e`.`odbc_date` AS `created`,
|
||||
`e`.`Id_Article` AS `itemFk`,
|
||||
`e`.`counter` AS `counter`,
|
||||
`e`.`checked` AS `checked`,
|
||||
`e`.`workerFk` AS `workerFk`
|
||||
FROM
|
||||
`vn2008`.`expeditions` `e`
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = function(Self) {
|
||||
require('../methods/item/crudItemBarcodes.js')(Self);
|
||||
require('../methods/item-barcode/crudItemBarcodes.js')(Self);
|
||||
};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = function(Self) {
|
||||
require('../methods/item/getLog.js')(Self);
|
||||
require('../methods/item-log/getLog.js')(Self);
|
||||
};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = function(Self) {
|
||||
require('../methods/item/crudItemNiches.js')(Self);
|
||||
require('../methods/item-niche/crudItemNiches.js')(Self);
|
||||
};
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = function(Self) {
|
||||
require('../methods/item/crudItemTags.js')(Self);
|
||||
require('../methods/item-tag/crudItemTags.js')(Self);
|
||||
};
|
||||
|
|
|
@ -1,22 +1,4 @@
|
|||
{
|
||||
"Item": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"ItemType": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Ink": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Origin": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Producer": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Intrastat": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"TaxClass": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
@ -26,9 +8,6 @@
|
|||
"TaxType": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Expence": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"ItemTag": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -5,5 +5,10 @@
|
|||
"The default consignee can not be unchecked": "No se puede desmarcar el consignatario predeterminado",
|
||||
"Unable to default a disabled consignee": "No se puede poner predeterminado un consignatario desactivado",
|
||||
"El método de pago seleccionado requiere que se especifique el IBAN": "El método de pago seleccionado requiere que se especifique el IBAN",
|
||||
"can't be blank": "can't be blank"
|
||||
"can't be blank": "can't be blank",
|
||||
"DNI Incorrecto": "DNI Incorrecto",
|
||||
"Ya existe un usuario con ese nombre": "Ya existe un usuario con ese nombre",
|
||||
"ValidationError: The `Item` instance is not valid. Details: `originFk` Cannot be blank (value: undefined).": "ValidationError: The `Item` instance is not valid. Details: `originFk` Cannot be blank (value: undefined).",
|
||||
"Error: ER_NO_REFERENCED_ROW_2: Cannot add or update a child row: a foreign key constraint fails (`vn2008`.`Articles`, CONSTRAINT `Articles_ibfk_5` FOREIGN KEY (`tipo_id`) REFERENCES `Tipos` (`tipo_id`) ON UPDATE CASCADE)": "Error: ER_NO_REFERENCED_ROW_2: Cannot add or update a child row: a foreign key constraint fails (`vn2008`.`Articles`, CONSTRAINT `Articles_ibfk_5` FOREIGN KEY (`tipo_id`) REFERENCES `Tipos` (`tipo_id`) ON UPDATE CASCADE)",
|
||||
"Error: ER_NO_REFERENCED_ROW_2: Cannot add or update a child row: a foreign key constraint fails (`vn2008`.`Articles`, CONSTRAINT `expenceFk` FOREIGN KEY (`expenceFk`) REFERENCES `Gastos` (`Id_Gasto`) ON UPDATE CASCADE)": "Error: ER_NO_REFERENCED_ROW_2: Cannot add or update a child row: a foreign key constraint fails (`vn2008`.`Articles`, CONSTRAINT `expenceFk` FOREIGN KEY (`expenceFk`) REFERENCES `Gastos` (`Id_Gasto`) ON UPDATE CASCADE)"
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
var UserError = require('../../../../loopback/common/helpers').UserError;
|
||||
var UserError = require('../../helpers').UserError;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('clone', {
|
||||
|
@ -27,7 +27,7 @@ module.exports = Self => {
|
|||
id: itemId
|
||||
},
|
||||
include: [
|
||||
{relation: "itemTag", scope: {order: "priority ASC", include: {relation: "tag"}}}
|
||||
{relation: 'itemTag', scope: {order: 'priority ASC', include: {relation: 'tag'}}}
|
||||
]
|
||||
};
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
module.exports = Self => {
|
||||
Self.installMethod('filter', filterParams);
|
||||
|
||||
function filterParams(params) {
|
||||
let filters = {
|
||||
where: {},
|
||||
skip: (params.page - 1) * params.size,
|
||||
limit: params.size,
|
||||
order: params.order || 'created DESC'
|
||||
};
|
||||
|
||||
delete params.page;
|
||||
delete params.size;
|
||||
delete params.order;
|
||||
|
||||
if (params.search) {
|
||||
filters.where.and = [
|
||||
{
|
||||
or: [
|
||||
{id: params.search},
|
||||
{name: {regexp: params.search}}
|
||||
]
|
||||
}
|
||||
];
|
||||
delete params.search;
|
||||
}
|
||||
|
||||
Object.keys(params).forEach(
|
||||
key => {
|
||||
if (filters.where.and) {
|
||||
let filter = {};
|
||||
filter[key] = (key === 'nickname') ? {regexp: params[key]} : params[key];
|
||||
filters.where.and.push(filter);
|
||||
} else {
|
||||
filters.where[key] = (key === 'nickname') ? {regexp: params[key]} : params[key];
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return filters;
|
||||
}
|
||||
};
|
|
@ -41,5 +41,13 @@
|
|||
"model": "AgencyType",
|
||||
"foreignKey": "agencyTypeFk"
|
||||
}
|
||||
},
|
||||
"acls": [
|
||||
{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -156,6 +156,11 @@
|
|||
"type": "hasMany",
|
||||
"model": "Greuge",
|
||||
"foreignKey": "clientFk"
|
||||
},
|
||||
"creditClassifications": {
|
||||
"type": "hasMany",
|
||||
"model": "CreditClassification",
|
||||
"foreignKey": "client"
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue