#972 ticket.tracking
This commit is contained in:
parent
5a53195574
commit
87a0a0bccc
|
@ -386,7 +386,8 @@ export default {
|
||||||
trackingButton: `vn-left-menu a[ui-sref="ticket.card.tracking.index"]`,
|
trackingButton: `vn-left-menu a[ui-sref="ticket.card.tracking.index"]`,
|
||||||
createStateButton: `${components.vnFloatButton}`,
|
createStateButton: `${components.vnFloatButton}`,
|
||||||
stateAutocomplete: 'vn-ticket-tracking-edit vn-autocomplete[field="$ctrl.ticket.stateFk"]',
|
stateAutocomplete: 'vn-ticket-tracking-edit vn-autocomplete[field="$ctrl.ticket.stateFk"]',
|
||||||
saveButton: `${components.vnSubmit}`
|
saveButton: `${components.vnSubmit}`,
|
||||||
|
cancelButton: `vn-ticket-tracking-edit vn-button[ui-sref="ticket.card.tracking.index"]`
|
||||||
},
|
},
|
||||||
ticketBasicData: {
|
ticketBasicData: {
|
||||||
basicDataButton: `vn-left-menu a[ui-sref="ticket.card.data.stepOne"]`,
|
basicDataButton: `vn-left-menu a[ui-sref="ticket.card.data.stepOne"]`,
|
||||||
|
@ -437,8 +438,8 @@ export default {
|
||||||
saveServiceButton: `${components.vnSubmit}`
|
saveServiceButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
createStateView: {
|
createStateView: {
|
||||||
stateAutocomplete: `vn-autocomplete[field="$ctrl.ticket.stateFk"]`,
|
stateAutocomplete: `vn-autocomplete[field="$ctrl.stateFk"]`,
|
||||||
clearStateInputButton: `vn-autocomplete[field="$ctrl.ticket.stateFk"] > div > div > div > vn-icon > i`,
|
clearStateInputButton: `vn-autocomplete[field="$ctrl.stateFk"] > div > div > div > vn-icon > i`,
|
||||||
saveStateButton: `${components.vnSubmit}`
|
saveStateButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
claimsIndex: {
|
claimsIndex: {
|
||||||
|
|
|
@ -25,27 +25,19 @@ describe('Ticket Create new tracking state path', () => {
|
||||||
.click(selectors.createStateView.saveStateButton)
|
.click(selectors.createStateView.saveStateButton)
|
||||||
.waitForLastSnackbar();
|
.waitForLastSnackbar();
|
||||||
|
|
||||||
expect(result).toEqual('No changes to save');
|
expect(result).toEqual('State cannot be blank');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should attempt create a new state then clear and save it`, async() => {
|
it(`should attempt create a new state then clear and save it`, async() => {
|
||||||
let result = await nightmare
|
let result = await nightmare
|
||||||
.autocompleteSearch(selectors.createStateView.stateAutocomplete, '¿Fecha?')
|
.autocompleteSearch(selectors.createStateView.stateAutocomplete, '¿Fecha?')
|
||||||
.waitToClick(selectors.createStateView.clearStateInputButton)
|
.waitToClick(selectors.createStateView.clearStateInputButton)
|
||||||
.click(selectors.createStateView.saveStateButton)
|
.waitToClick(selectors.createStateView.saveStateButton)
|
||||||
.waitForLastSnackbar();
|
.waitForLastSnackbar();
|
||||||
|
|
||||||
expect(result).toEqual('Data saved!');
|
expect(result).toEqual('State cannot be blank');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should again access to the create state view by clicking the create floating button', async() => {
|
|
||||||
let url = await nightmare
|
|
||||||
.click(selectors.ticketTracking.createStateButton)
|
|
||||||
.wait(selectors.createStateView.stateAutocomplete)
|
|
||||||
.parsedUrl();
|
|
||||||
|
|
||||||
expect(url.hash).toContain('tracking/edit');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should create a new state`, async() => {
|
it(`should create a new state`, async() => {
|
||||||
let result = await nightmare
|
let result = await nightmare
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
"That payment method requires an IBAN": "El método de pago seleccionado requiere un IBAN",
|
"That payment method requires an IBAN": "El método de pago seleccionado requiere un IBAN",
|
||||||
"That payment method requires a BIC": "El método de pago seleccionado requiere un BIC",
|
"That payment method requires a BIC": "El método de pago seleccionado requiere un BIC",
|
||||||
"State cannot be blank": "El estado no puede estar en blanco",
|
"State cannot be blank": "El estado no puede estar en blanco",
|
||||||
|
"Worker cannot be blank": "El trabajador no puede estar en blanco",
|
||||||
"Cannot change the payment method if no salesperson": "No se puede cambiar la forma de pago si no hay comercial asignado",
|
"Cannot change the payment method if no salesperson": "No se puede cambiar la forma de pago si no hay comercial asignado",
|
||||||
"can't be blank": "El campo no puede estar vacío",
|
"can't be blank": "El campo no puede estar vacío",
|
||||||
"Observation type cannot be blank": "El tipo de observación no puede estar en blanco",
|
"Observation type cannot be blank": "El tipo de observación no puede estar en blanco",
|
||||||
|
|
|
@ -25,18 +25,25 @@ module.exports = Self => {
|
||||||
let models = Self.app.models;
|
let models = Self.app.models;
|
||||||
let isProduction;
|
let isProduction;
|
||||||
let isEditable = await Self.app.models.Ticket.isEditable(params.ticketFk);
|
let isEditable = await Self.app.models.Ticket.isEditable(params.ticketFk);
|
||||||
|
let assignedState = await Self.app.models.State.findOne({where: {code: 'PICKER_DESIGNED'}});
|
||||||
|
let isAssigned = assignedState.id === params.stateFk;
|
||||||
|
let currentUserId;
|
||||||
|
|
||||||
if (ctx.req.accessToken) {
|
if (ctx.req.accessToken) {
|
||||||
let token = ctx.req.accessToken;
|
let token = ctx.req.accessToken;
|
||||||
let currentUserId = token && token.userId;
|
currentUserId = token && token.userId;
|
||||||
isProduction = await models.Account.hasRole(currentUserId, 'Production');
|
isProduction = await models.Account.hasRole(currentUserId, 'production');
|
||||||
|
isSalesperson = await models.Account.hasRole(currentUserId, 'salesPerson');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!isEditable && !isProduction) || (isEditable && !isAssigned && isSalesperson) || (!isSalesperson && !isProduction))
|
||||||
|
throw new UserError(`You don't have enough privileges to change the state of this ticket`);
|
||||||
|
|
||||||
|
if (!isAssigned) {
|
||||||
let worker = await models.Worker.findOne({where: {userFk: currentUserId}});
|
let worker = await models.Worker.findOne({where: {userFk: currentUserId}});
|
||||||
params.workerFk = worker.id;
|
params.workerFk = worker.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isEditable && !isProduction)
|
|
||||||
throw new UserError(`You don't have enough privileges to change the state of this ticket`);
|
|
||||||
|
|
||||||
return await Self.app.models.TicketTracking.create(params);
|
return await Self.app.models.TicketTracking.create(params);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,18 +3,18 @@ const app = require(`${serviceRoot}/server/server`);
|
||||||
describe('ticket changeState()', () => {
|
describe('ticket changeState()', () => {
|
||||||
let ticket;
|
let ticket;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async() => {
|
||||||
let originalTicket = await app.models.Ticket.findOne({where: {id: 16}});
|
let originalTicket = await app.models.Ticket.findOne({where: {id: 16}});
|
||||||
originalTicket.id = null;
|
originalTicket.id = null;
|
||||||
ticket = await app.models.Ticket.create(originalTicket);
|
ticket = await app.models.Ticket.create(originalTicket);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async() => {
|
||||||
await app.models.Ticket.destroyById(ticket.id);
|
await app.models.Ticket.destroyById(ticket.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if the ticket is not editable and the user isnt production', async () => {
|
it('should throw an error if the ticket is not editable and the user isnt production', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 110}}};
|
let ctx = {req: {accessToken: {userId: 18}}};
|
||||||
let params = {ticketFk: 2, stateFk: 3};
|
let params = {ticketFk: 2, stateFk: 3};
|
||||||
let error;
|
let error;
|
||||||
try {
|
try {
|
||||||
|
@ -26,26 +26,66 @@ describe('ticket changeState()', () => {
|
||||||
expect(error).toEqual(new Error(`You don't have enough privileges to change the state of this ticket`));
|
expect(error).toEqual(new Error(`You don't have enough privileges to change the state of this ticket`));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to create a ticket tracking line for a not editable ticket if the user has the production role', async () => {
|
it('should throw an error if the state is assigned and theres not worker in params', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 50}}};
|
let ctx = {req: {accessToken: {userId: 18}}};
|
||||||
let params = {ticketFk: 20, stateFk: 3};
|
let assignedState = await app.models.State.findOne({where: {code: 'PICKER_DESIGNED'}});
|
||||||
|
let params = {ticketFk: 11, stateFk: assignedState.id};
|
||||||
|
let error;
|
||||||
|
try {
|
||||||
|
await app.models.TicketTracking.changeState(ctx, params);
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toEqual('La instancia `TicketTracking` no es válida. Detalles: `workerFk` Worker cannot be blank (value: undefined).');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if a worker thats not production tries to change the state to one thats not assigned', async() => {
|
||||||
|
let ctx = {req: {accessToken: {userId: 110}}};
|
||||||
|
let params = {ticketFk: 11, stateFk: 3};
|
||||||
|
let error;
|
||||||
|
try {
|
||||||
|
await app.models.TicketTracking.changeState(ctx, params);
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toEqual(`You don't have enough privileges to change the state of this ticket`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to create a ticket tracking line for a not editable ticket if the user has the production role', async() => {
|
||||||
|
let ctx = {req: {accessToken: {userId: 49}}};
|
||||||
|
let params = {ticketFk: ticket.id, stateFk: 3};
|
||||||
|
|
||||||
let res = await app.models.TicketTracking.changeState(ctx, params);
|
let res = await app.models.TicketTracking.changeState(ctx, params);
|
||||||
|
|
||||||
expect(res.__data.ticketFk).toBe(params.ticketFk);
|
expect(res.__data.ticketFk).toBe(params.ticketFk);
|
||||||
expect(res.__data.stateFk).toBe(params.stateFk);
|
expect(res.__data.stateFk).toBe(params.stateFk);
|
||||||
expect(res.__data.workerFk).toBe(50);
|
expect(res.__data.workerFk).toBe(49);
|
||||||
expect(res.__data.id).toBeDefined();
|
expect(res.__data.id).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return an array with the created ticket tracking line', async () => {
|
it('return an array with the created ticket tracking line', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 108}}};
|
let ctx = {req: {accessToken: {userId: 49}}};
|
||||||
let params = {ticketFk: ticket.id, stateFk: 3};
|
let params = {ticketFk: ticket.id, stateFk: 3};
|
||||||
let res = await app.models.TicketTracking.changeState(ctx, params);
|
let res = await app.models.TicketTracking.changeState(ctx, params);
|
||||||
|
|
||||||
expect(res.__data.ticketFk).toBe(params.ticketFk);
|
expect(res.__data.ticketFk).toBe(params.ticketFk);
|
||||||
expect(res.__data.stateFk).toBe(params.stateFk);
|
expect(res.__data.stateFk).toBe(params.stateFk);
|
||||||
expect(res.__data.workerFk).toBe(110);
|
expect(res.__data.workerFk).toBe(49);
|
||||||
|
expect(res.__data.id).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('return an array with the created ticket tracking line when the user is salesperson, uses the state assigned and thes a workerFk given', async() => {
|
||||||
|
let ctx = {req: {accessToken: {userId: 18}}};
|
||||||
|
let assignedState = await app.models.State.findOne({where: {code: 'PICKER_DESIGNED'}});
|
||||||
|
let params = {ticketFk: ticket.id, stateFk: assignedState.id, workerFk: 1};
|
||||||
|
let res = await app.models.TicketTracking.changeState(ctx, params);
|
||||||
|
|
||||||
|
expect(res.__data.ticketFk).toBe(params.ticketFk);
|
||||||
|
expect(res.__data.stateFk).toBe(params.stateFk);
|
||||||
|
expect(res.__data.workerFk).toBe(params.workerFk);
|
||||||
|
expect(res.__data.workerFk).toBe(1);
|
||||||
expect(res.__data.id).toBeDefined();
|
expect(res.__data.id).toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,4 +2,5 @@ module.exports = function(Self) {
|
||||||
require('../methods/ticket-tracking/changeState')(Self);
|
require('../methods/ticket-tracking/changeState')(Self);
|
||||||
|
|
||||||
Self.validatesPresenceOf('stateFk', {message: 'State cannot be blank'});
|
Self.validatesPresenceOf('stateFk', {message: 'State cannot be blank'});
|
||||||
|
Self.validatesPresenceOf('workerFk', {message: 'Worker cannot be blank'});
|
||||||
};
|
};
|
||||||
|
|
|
@ -142,7 +142,7 @@
|
||||||
"params": {
|
"params": {
|
||||||
"ticket": "$ctrl.ticket"
|
"ticket": "$ctrl.ticket"
|
||||||
},
|
},
|
||||||
"acl": ["production", "administrative"]
|
"acl": ["production", "administrative", "salesPerson"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url" : "/sale-checked",
|
"url" : "/sale-checked",
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<mg-ajax path="/ticket/api/TicketTrackings/changeState" options="vnPost"></mg-ajax>
|
<mg-ajax path="/api/TicketTrackings/changeState" options="vnPost"></mg-ajax>
|
||||||
<vn-watcher
|
<vn-watcher
|
||||||
vn-id="watcher"
|
vn-id="watcher"
|
||||||
data="$ctrl.ticket"
|
data="$ctrl.params"
|
||||||
form="form"
|
form="form">
|
||||||
save="post">
|
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" compact>
|
<form name="form" ng-submit="$ctrl.onSubmit()" compact>
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
|
@ -11,11 +10,23 @@
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
vn-one
|
vn-one
|
||||||
field="$ctrl.ticket.stateFk"
|
field="$ctrl.stateFk"
|
||||||
url="/ticket/api/States"
|
url="/ticket/api/States"
|
||||||
label="State"
|
label="State"
|
||||||
vn-focus>
|
vn-focus>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
|
<vn-autocomplete
|
||||||
|
vn-one
|
||||||
|
ng-if="$ctrl.isPickerDesignedState"
|
||||||
|
field="$ctrl.workerFk"
|
||||||
|
url="/client/api/Clients/activeWorkersWithRole"
|
||||||
|
show-field="firstName"
|
||||||
|
search-function="{firstName: $search}"
|
||||||
|
value-field="id"
|
||||||
|
where="{role: 'employee'}"
|
||||||
|
label="Worker">
|
||||||
|
<tpl-item>{{firstName}} {{name}}</tpl-item>
|
||||||
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-button-bar>
|
<vn-button-bar>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor($scope, $state, vnApp, $translate) {
|
constructor($scope, $state, vnApp, $translate, $http) {
|
||||||
|
this.$http = $http;
|
||||||
this.$ = $scope;
|
this.$ = $scope;
|
||||||
this.$state = $state;
|
this.$state = $state;
|
||||||
this.vnApp = vnApp;
|
this.vnApp = vnApp;
|
||||||
|
@ -9,17 +10,60 @@ class Controller {
|
||||||
this.ticket = {
|
this.ticket = {
|
||||||
ticketFk: $state.params.id
|
ticketFk: $state.params.id
|
||||||
};
|
};
|
||||||
|
this.params = {ticketFk: $state.params.id};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
this.getPickerDesignedState();
|
||||||
|
}
|
||||||
|
|
||||||
|
set stateFk(value) {
|
||||||
|
this.params.stateFk = value;
|
||||||
|
this.isPickerDesignedState = this.getIsPickerDesignedState(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get stateFk() {
|
||||||
|
return this.params.stateFk;
|
||||||
|
}
|
||||||
|
|
||||||
|
set workerFk(value) {
|
||||||
|
this.params.workerFk = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get workerFk() {
|
||||||
|
return this.params.workerFk;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPickerDesignedState() {
|
||||||
|
let filter = {
|
||||||
|
where: {
|
||||||
|
code: 'PICKER_DESIGNED'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let json = encodeURIComponent(JSON.stringify(filter));
|
||||||
|
this.$http.get(`/api/States?filter=${json}`).then(res => {
|
||||||
|
if (res && res.data)
|
||||||
|
this.pickerDesignedState = res.data[0].id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getIsPickerDesignedState(value) {
|
||||||
|
if (value == this.pickerDesignedState)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.$.watcher.submit().then(
|
this.$http.post(`/api/TicketTrackings/changeState`, this.params).then(() => {
|
||||||
() => {
|
this.$.watcher.updateOriginalData();
|
||||||
this.card.reload();
|
this.card.reload();
|
||||||
|
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||||
this.$state.go('ticket.card.tracking.index');
|
this.$state.go('ticket.card.tracking.index');
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Controller.$inject = ['$scope', '$state', 'vnApp', '$translate'];
|
Controller.$inject = ['$scope', '$state', 'vnApp', '$translate', '$http'];
|
||||||
|
|
||||||
ngModule.component('vnTicketTrackingEdit', {
|
ngModule.component('vnTicketTrackingEdit', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
import './index';
|
||||||
|
|
||||||
|
describe('Ticket', () => {
|
||||||
|
describe('Component vnTicketTrackingEdit', () => {
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(ngModule('ticket'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, _$httpBackend_, $translate, vnApp) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
controller = $componentController('vnTicketTrackingEdit');
|
||||||
|
controller.ticket = {id: 1};
|
||||||
|
controller.$ = {watcher: {updateOriginalData: () => {}}};
|
||||||
|
controller.card = {reload: () => {}};
|
||||||
|
controller.vnApp = {showSuccess: () => {}};
|
||||||
|
controller.$translate = $translate;
|
||||||
|
controller.vnApp = vnApp;
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('stateFk setter/getter', () => {
|
||||||
|
it('should set params.stateFk and set isPickerDesignedState', () => {
|
||||||
|
let stateFk = {id: 1};
|
||||||
|
controller.stateFk = stateFk;
|
||||||
|
|
||||||
|
expect(controller.params.stateFk).toEqual(stateFk);
|
||||||
|
expect(controller.isPickerDesignedState).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('workerFk setter', () => {
|
||||||
|
it('should set params.workerFk', () => {
|
||||||
|
controller.workerFk = 1;
|
||||||
|
|
||||||
|
expect(controller.params.workerFk).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getPickerDesignedState()', () => {
|
||||||
|
it('should get the state that has the code PICKER_DESIGNED', () => {
|
||||||
|
let filter = {
|
||||||
|
where: {
|
||||||
|
code: 'PICKER_DESIGNED'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let json = encodeURIComponent(JSON.stringify(filter));
|
||||||
|
$httpBackend.expectGET(`/api/States?filter=${json}`).respond([{id: 22}]);
|
||||||
|
controller.getPickerDesignedState();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.pickerDesignedState).toEqual(22);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onSubmit()', () => {
|
||||||
|
it('should POST the data, call updateOriginalData, reload, showSuccess and go functions', () => {
|
||||||
|
controller.params = {stateFk: 22, workerFk: 101};
|
||||||
|
spyOn(controller.card, 'reload');
|
||||||
|
spyOn(controller.$.watcher, 'updateOriginalData');
|
||||||
|
spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
spyOn(controller.$state, 'go');
|
||||||
|
|
||||||
|
$httpBackend.expectPOST(`/api/TicketTrackings/changeState`, controller.params).respond({});
|
||||||
|
controller.onSubmit();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.card.reload).toHaveBeenCalledWith();
|
||||||
|
expect(controller.$.watcher.updateOriginalData).toHaveBeenCalledWith();
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith(controller.$translate.instant('Data saved!'));
|
||||||
|
expect(controller.$state.go).toHaveBeenCalledWith('ticket.card.tracking.index');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -34,6 +34,6 @@
|
||||||
<vn-pagination model="model"></vn-pagination>
|
<vn-pagination model="model"></vn-pagination>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
<a ui-sref="ticket.card.tracking.edit" vn-bind="+" vn-visible-by="production, administrative" fixed-bottom-right>
|
<a ui-sref="ticket.card.tracking.edit" vn-bind="+" vn-visible-by="production, administrative, salesperson" fixed-bottom-right>
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
<vn-float-button icon="add"></vn-float-button>
|
||||||
</a>
|
</a>
|
|
@ -6,15 +6,15 @@ class Controller {
|
||||||
this.filter = {
|
this.filter = {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
relation: "worker",
|
relation: 'worker',
|
||||||
scope: {
|
scope: {
|
||||||
fields: ["firstName", "name"]
|
fields: ['firstName', 'name']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
relation: "state",
|
relation: 'state',
|
||||||
scope: {
|
scope: {
|
||||||
fields: ["name"]
|
fields: ['name']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue