Bug #452 quitamos servicio production
This commit is contained in:
parent
08ef7dee96
commit
c4e0fc74a3
|
@ -2,4 +2,5 @@ node_modules
|
||||||
build
|
build
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
.eslintcache
|
.eslintcache
|
||||||
|
.env.json
|
|
@ -20,10 +20,10 @@
|
||||||
<vn-label-value label="Created"
|
<vn-label-value label="Created"
|
||||||
value="{{$ctrl.claim.created | dateTime: 'dd/MM/yyyy'}}">
|
value="{{$ctrl.claim.created | dateTime: 'dd/MM/yyyy'}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value label="Buyer"
|
<vn-label-value label="Salesperson"
|
||||||
value="{{$ctrl.claim.client.salesPerson.firstName}} {{$ctrl.claim.client.salesPerson.name}}">
|
value="{{$ctrl.claim.client.salesPerson.firstName}} {{$ctrl.claim.client.salesPerson.name}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value label="Attended"
|
<vn-label-value label="Attended by"
|
||||||
value="{{$ctrl.claim.worker.firstName}} {{$ctrl.claim.worker.name}}">
|
value="{{$ctrl.claim.worker.firstName}} {{$ctrl.claim.worker.name}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
<vn-crud-model
|
||||||
|
vn-id="model"
|
||||||
|
url="claim/api/ClaimBeginnings"
|
||||||
|
filter="$ctrl.filter"
|
||||||
|
data="$ctrl.salesClaimed" on-data-change="$ctrl.onDataChange()">
|
||||||
|
</vn-crud-model>
|
||||||
|
<vn-vertical>
|
||||||
|
<vn-card pad-large>
|
||||||
|
<vn-vertical>
|
||||||
|
<vn-title>Detail</vn-title>
|
||||||
|
<vn-table model="model">
|
||||||
|
<vn-thead>
|
||||||
|
<vn-tr>
|
||||||
|
<vn-th number>Id</vn-th>
|
||||||
|
<vn-th number>Landed</vn-th>
|
||||||
|
<vn-th number>Quantity</vn-th>
|
||||||
|
<vn-th number>Claimed</vn-th>
|
||||||
|
<vn-th number>Description</vn-th>
|
||||||
|
<vn-th number>Price</vn-th>
|
||||||
|
<vn-th number>Disc.</vn-th>
|
||||||
|
<vn-th number>Total</vn-th>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-thead>
|
||||||
|
<vn-tbody>
|
||||||
|
<vn-tr ng-repeat="saleClaimed in $ctrl.salesClaimed" vn-repeat-last on-last="$ctrl.focusLastInput()">
|
||||||
|
<vn-td number>{{saleClaimed.sale.id}}</vn-td>
|
||||||
|
<vn-td number>{{saleClaimed.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}}</vn-td>
|
||||||
|
<vn-td number>{{saleClaimed.sale.quantity}}</vn-td>
|
||||||
|
<vn-td number>
|
||||||
|
<vn-textfield
|
||||||
|
id="claimedQuantity"
|
||||||
|
model="saleClaimed.quantity"
|
||||||
|
on-change="$ctrl.setClaimedQuantity(saleClaimed.id, saleClaimed.quantity)"
|
||||||
|
type="text">
|
||||||
|
</vn-textfield>
|
||||||
|
</vn-td>
|
||||||
|
<vn-td number>{{saleClaimed.sale.concept}}</vn-td>
|
||||||
|
<vn-td number>{{saleClaimed.sale.price | currency:'€':2}}</vn-td>
|
||||||
|
<vn-td number>{{saleClaimed.sale.discount}} %</vn-td>
|
||||||
|
<vn-td number>
|
||||||
|
{{(saleClaimed.sale.quantity * saleClaimed.sale.price) -
|
||||||
|
((saleClaimed.sale.discount *
|
||||||
|
(saleClaimed.sale.quantity * saleClaimed.sale.price))/100) | currency:'€':2
|
||||||
|
}}
|
||||||
|
</vn-td>
|
||||||
|
<vn-td number>
|
||||||
|
<vn-icon-button
|
||||||
|
medium-grey
|
||||||
|
margin-medium-v
|
||||||
|
vn-tooltip="Remove tag"
|
||||||
|
icon="remove_circle_outline"
|
||||||
|
ng-click="$ctrl.deleteClaimedSale(saleClaimed.id)"
|
||||||
|
tabindex="-1">
|
||||||
|
</vn-icon-button>
|
||||||
|
</vn-td>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-tbody>
|
||||||
|
<vn-empty-rows ng-if="model.data.length === 0" translate>
|
||||||
|
No results
|
||||||
|
</vn-empty-rows>
|
||||||
|
</vn-table>
|
||||||
|
<vn-one pad-medium-top>
|
||||||
|
<vn-icon-button
|
||||||
|
vn-bind="+"
|
||||||
|
vn-tooltip="Add tag"
|
||||||
|
icon="add_circle"
|
||||||
|
ng-click="$ctrl.openAddSalesDialog()">
|
||||||
|
</vn-icon-button>
|
||||||
|
</vn-one>
|
||||||
|
</vn-vertical>
|
||||||
|
</vn-card>
|
||||||
|
|
||||||
|
<!-- Add Lines Dialog -->
|
||||||
|
<vn-dialog
|
||||||
|
vn-id="addSales">
|
||||||
|
<tpl-body>
|
||||||
|
<h3 translate>Claimable sales from ticket</h3><h3> {{$ctrl.claim.ticketFk}}</h3>
|
||||||
|
<vn-table>
|
||||||
|
<vn-thead>
|
||||||
|
<vn-tr>
|
||||||
|
<vn-th number>Id</vn-th>
|
||||||
|
<vn-th number>Landed</vn-th>
|
||||||
|
<vn-th number>Quantity</vn-th>
|
||||||
|
<vn-th number>Description</vn-th>
|
||||||
|
<vn-th number>Price</vn-th>
|
||||||
|
<vn-th number>Disc.</vn-th>
|
||||||
|
<vn-th number>Total</vn-th>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-thead>
|
||||||
|
<vn-tbody>
|
||||||
|
<vn-tr ng-repeat="sale in $ctrl.salesToClaim" class="clickable" ng-click="$ctrl.addClaimedSale(sale.saleFk)">
|
||||||
|
<vn-td number>{{sale.saleFk}}</vn-td>
|
||||||
|
<vn-td number>{{sale.landed | dateTime: 'dd/MM/yyyy'}}</vn-td>
|
||||||
|
<vn-td number>{{sale.quantity}}</vn-td>
|
||||||
|
<vn-td number>{{sale.concept}}</vn-td>
|
||||||
|
<vn-td number>{{sale.price | currency:'€':2}}</vn-td>
|
||||||
|
<vn-td number>{{sale.discount}} %</vn-td>
|
||||||
|
<vn-td number>
|
||||||
|
{{(sale.quantity * sale.price) - ((sale.discount * (sale.quantity * sale.price))/100) | currency:'€':2}}
|
||||||
|
</vn-td>
|
||||||
|
</vn-tr>
|
||||||
|
</vn-tbody>
|
||||||
|
<vn-empty-rows ng-if="model.data.length === 0" translate>
|
||||||
|
No results
|
||||||
|
</vn-empty-rows>
|
||||||
|
</vn-table>
|
||||||
|
</tpl-body>
|
||||||
|
</vn-dialog>
|
|
@ -0,0 +1,84 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
class Controller {
|
||||||
|
constructor($state, $scope, $http, $translate, vnApp) {
|
||||||
|
this.$state = $state;
|
||||||
|
this.$ = $scope;
|
||||||
|
this.$http = $http;
|
||||||
|
this.$translate = $translate;
|
||||||
|
this.vnApp = vnApp;
|
||||||
|
this.filter = {
|
||||||
|
where: {claimFk: $state.params.id},
|
||||||
|
include: [
|
||||||
|
{relation: 'sale',
|
||||||
|
scope: {
|
||||||
|
fields: ['concept', 'ticketFk', 'price', 'quantity', 'discount'],
|
||||||
|
include: {
|
||||||
|
relation: 'ticket'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
openAddSalesDialog() {
|
||||||
|
this.getClaimableFromTicket();
|
||||||
|
this.$.addSales.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
getClaimableFromTicket() {
|
||||||
|
let json = encodeURIComponent(JSON.stringify(this.claim.ticketFk));
|
||||||
|
|
||||||
|
let query = `/api/Sales/getClaimableFromTicket?ticketFk=${json}`;
|
||||||
|
this.$http.get(query).then(res => {
|
||||||
|
if (res.data) {
|
||||||
|
this.salesToClaim = res.data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addClaimedSale(saleFk) {
|
||||||
|
let saleToAdd = {saleFk: saleFk, claimFk: this.claim.id, quantity: 0};
|
||||||
|
let query = `claim/api/ClaimBeginnings/`;
|
||||||
|
this.$http.post(query, saleToAdd).then(() => {
|
||||||
|
this.$.model.refresh();
|
||||||
|
this.$.addSales.hide();
|
||||||
|
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteClaimedSale(id) {
|
||||||
|
let json = encodeURIComponent(JSON.stringify(id));
|
||||||
|
let query = `claim/api/ClaimBeginnings/${json}`;
|
||||||
|
this.$http.delete(query).then(() => {
|
||||||
|
this.$.model.refresh();
|
||||||
|
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
focusLastInput() {
|
||||||
|
let inputs = document.querySelectorAll("#claimedQuantity");
|
||||||
|
inputs[inputs.length - 1].querySelector("input").select();
|
||||||
|
}
|
||||||
|
|
||||||
|
setClaimedQuantity(id, claimedQuantity) {
|
||||||
|
let params = {id: id, quantity: claimedQuantity};
|
||||||
|
let query = `claim/api/ClaimBeginnings/`;
|
||||||
|
this.$http.patch(query, params).then(() => {
|
||||||
|
this.$.model.refresh();
|
||||||
|
this.vnApp.showSuccess(this.$translate.instant('Data saved!'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.$inject = ['$state', '$scope', '$http', '$translate', 'vnApp'];
|
||||||
|
|
||||||
|
ngModule.component('vnClaimDetail', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller,
|
||||||
|
bindings: {
|
||||||
|
claim: '<'
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,94 @@
|
||||||
|
import './index.js';
|
||||||
|
|
||||||
|
describe('claim', () => {
|
||||||
|
describe('Component vnClaimDetail', () => {
|
||||||
|
let $componentController;
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
let $state;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
angular.mock.module('claim');
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_, $rootScope) => {
|
||||||
|
$componentController = _$componentController_;
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
|
$httpBackend.when('GET', 'claim/api/Claims/ClaimBeginnings').respond({});
|
||||||
|
$state = _$state_;
|
||||||
|
$state.params.id = 1;
|
||||||
|
|
||||||
|
controller = $componentController('vnClaimDetail', {$state: $state});
|
||||||
|
controller.claim = {ticketFk: 1};
|
||||||
|
controller.$.model = {refresh: () => {}};
|
||||||
|
controller.$.addSales = {
|
||||||
|
hide: () => {},
|
||||||
|
show: () => {}
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('openAddSalesDialog()', () => {
|
||||||
|
it('should call getClaimableFromTicket and $.addSales.show', () => {
|
||||||
|
controller.$ = {addSales: {show: () => {}}};
|
||||||
|
spyOn(controller, 'getClaimableFromTicket');
|
||||||
|
spyOn(controller.$.addSales, 'show');
|
||||||
|
controller.openAddSalesDialog();
|
||||||
|
|
||||||
|
expect(controller.getClaimableFromTicket).toHaveBeenCalledWith();
|
||||||
|
expect(controller.$.addSales.show).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getClaimableFromTicket()', () => {
|
||||||
|
it('should make a query and set salesToClaim', () => {
|
||||||
|
$httpBackend.expectGET(`/api/Sales/getClaimableFromTicket?ticketFk=1`).respond(200, 1);
|
||||||
|
controller.getClaimableFromTicket();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.salesToClaim).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addClaimedSale(saleFk)', () => {
|
||||||
|
it('should make a post and call refresh, hide and showSuccess', () => {
|
||||||
|
spyOn(controller.$.model, 'refresh');
|
||||||
|
spyOn(controller.$.addSales, 'hide');
|
||||||
|
spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
$httpBackend.expectPOST(`claim/api/ClaimBeginnings/`).respond({});
|
||||||
|
controller.addClaimedSale(1);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
||||||
|
expect(controller.$.addSales.hide).toHaveBeenCalledWith();
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('deleteClaimedSale(id)', () => {
|
||||||
|
it('should make a delete and call refresh and showSuccess', () => {
|
||||||
|
spyOn(controller.$.model, 'refresh');
|
||||||
|
spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
$httpBackend.expectDELETE(`claim/api/ClaimBeginnings/1`).respond({});
|
||||||
|
controller.deleteClaimedSale(1);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setClaimedQuantity(id, claimedQuantity)', () => {
|
||||||
|
it('should make a patch and call refresh and showSuccess', () => {
|
||||||
|
spyOn(controller.$.model, 'refresh');
|
||||||
|
spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
$httpBackend.expectPATCH(`claim/api/ClaimBeginnings/`).respond({});
|
||||||
|
controller.setClaimedQuantity(1, 1);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,7 @@
|
||||||
|
Claimed: Reclamados
|
||||||
|
Disc.: Dto.
|
||||||
|
Attended by: Atendida por
|
||||||
|
Landed: Recibido
|
||||||
|
Price: Precio
|
||||||
|
Claimable sales from ticket: Lineas reclamables del ticket
|
||||||
|
Detail: Detalles
|
|
@ -0,0 +1,20 @@
|
||||||
|
vn-claim-detail {
|
||||||
|
vn-textfield {
|
||||||
|
margin: 0!important;
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
||||||
|
vn-dialog[vn-id=addSales] {
|
||||||
|
tpl-body {
|
||||||
|
width: 950px;
|
||||||
|
div {
|
||||||
|
div.buttons {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
vn-table{
|
||||||
|
min-width: 950px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ export * from './module';
|
||||||
|
|
||||||
import './index/';
|
import './index/';
|
||||||
import './card';
|
import './card';
|
||||||
|
import './detail';
|
||||||
import './descriptor';
|
import './descriptor';
|
||||||
import './basic-data';
|
import './basic-data';
|
||||||
// import './summary';
|
// import './summary';
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
<vn-crud-model
|
<vn-crud-model
|
||||||
vn-id="model"
|
vn-id="model"
|
||||||
url="/client/api/ClientContacts"
|
url="/client/api/ClientContacts"
|
||||||
fields="['id', 'clientFk', 'name', 'phone']"
|
fields="['id', 'name', 'phone', 'clientFk']"
|
||||||
link="{clientFk: $ctrl.$stateParams.id}"
|
link="{clientFk: $ctrl.$stateParams.id}"
|
||||||
data="contacts" on-data-change="$ctrl.onDataChange()">
|
data="contacts">
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
|
|
||||||
<vn-watcher
|
<vn-watcher
|
||||||
vn-id="watcher"
|
vn-id="watcher"
|
||||||
data="contacts"
|
data="contacts"
|
||||||
|
@ -27,15 +26,16 @@
|
||||||
model="contact.phone"
|
model="contact.phone"
|
||||||
rule="clientContact.phone" vn-focus>
|
rule="clientContact.phone" vn-focus>
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-auto pad-medium-top>
|
<vn-none>
|
||||||
<vn-icon
|
<vn-icon
|
||||||
pointer
|
pointer
|
||||||
medium-grey
|
medium-grey
|
||||||
|
margin-medium-v
|
||||||
vn-tooltip="Remove contact"
|
vn-tooltip="Remove contact"
|
||||||
icon="remove_circle_outline"
|
icon="remove_circle_outline"
|
||||||
ng-click="$ctrl.remove($index)">
|
ng-click="model.remove($index)">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
</vn-one>
|
</vn-none>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-one>
|
<vn-one>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
|
|
|
@ -1,40 +1,30 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor($http, $scope, $stateParams, $translate, vnApp) {
|
constructor($scope, $stateParams, $translate) {
|
||||||
this.$http = $http;
|
|
||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
this.$stateParams = $stateParams;
|
this.$stateParams = $stateParams;
|
||||||
this.$translate = $translate;
|
this.$translate = $translate;
|
||||||
this.vnApp = vnApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
onDataChange() {
|
|
||||||
this.contacts = this.$scope.model.data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add() {
|
add() {
|
||||||
let data = {
|
this.$scope.model.insert({
|
||||||
clientFk: this.client.id,
|
clientFk: this.client.id,
|
||||||
name: this.$translate.instant('Phone'),
|
name: this.$translate.instant('Phone'),
|
||||||
phone: null
|
phone: null
|
||||||
};
|
});
|
||||||
this.contacts.push(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
remove(index) {
|
|
||||||
this.contacts.splice(index, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
this.$scope.watcher.check();
|
this.$scope.watcher.check();
|
||||||
this.$scope.watcher.realSubmit()
|
this.$scope.model.save().then(() => {
|
||||||
.then(() => this.$scope.model.save(true))
|
this.$scope.watcher.notifySaved();
|
||||||
.then(() => this.$scope.watcher.notifySaved());
|
this.$scope.model.refresh();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$http', '$scope', '$stateParams', '$translate', 'vnApp'];
|
Controller.$inject = ['$scope', '$stateParams', '$translate'];
|
||||||
|
|
||||||
ngModule.component('vnClientContact', {
|
ngModule.component('vnClientContact', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
import {watcher} from '../helpers/watcherHelper.js';
|
|
||||||
|
|
||||||
describe('Client', () => {
|
|
||||||
describe('Component vnClientContact', () => {
|
|
||||||
let $componentController;
|
|
||||||
let $scope;
|
|
||||||
let $state;
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
angular.mock.module('client');
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_, _$httpBackend_) => {
|
|
||||||
$componentController = _$componentController_;
|
|
||||||
$state = _$state_;
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
$scope.form = {$invalid: false};
|
|
||||||
$scope.model = {
|
|
||||||
refresh: () => {},
|
|
||||||
data: [
|
|
||||||
{id: 1, name: 'My contact 1', phone: '123456789'},
|
|
||||||
{id: 2, name: 'My contact 2', phone: '123456789'},
|
|
||||||
{id: 3, name: 'My contact 3', phone: '123456789'}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
$scope.watcher = watcher;
|
|
||||||
controller = $componentController('vnClientContact', {$scope: $scope}, {$state: $state});
|
|
||||||
controller.client = {
|
|
||||||
id: 101
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('onDataChange()', () => {
|
|
||||||
it('should define contacts and oldInstances properties into controller', () => {
|
|
||||||
controller.onDataChange();
|
|
||||||
|
|
||||||
expect(controller.contacts).toBeDefined();
|
|
||||||
expect(controller.contacts.length).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('add / remove tags', () => {
|
|
||||||
it('should add one empty contact into controller contacts collection', () => {
|
|
||||||
controller.contacts = [];
|
|
||||||
controller.add();
|
|
||||||
|
|
||||||
expect(controller.contacts.length).toEqual(1);
|
|
||||||
expect(controller.contacts[0].id).toBe(undefined);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove a contact that occupies the position in the index', () => {
|
|
||||||
let index = 2;
|
|
||||||
controller.onDataChange();
|
|
||||||
controller.remove(index);
|
|
||||||
|
|
||||||
expect(controller.contacts.length).toEqual(2);
|
|
||||||
expect(controller.contacts[index]).toBe(undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
xdescribe('onSubmit()', () => {
|
|
||||||
it("should perfom a query to delete contacts", () => {
|
|
||||||
controller.$scope.model.data = [
|
|
||||||
{id: 1, name: 'My contact 1', phone: '123456789'},
|
|
||||||
{id: 2, name: 'My contact 2', phone: '123456789'}
|
|
||||||
];
|
|
||||||
spyOn(controller.$scope.watcher, 'notifySaved');
|
|
||||||
|
|
||||||
controller.onSubmit();
|
|
||||||
|
|
||||||
expect(controller.$scope.watcher.notifySaved).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,14 +0,0 @@
|
||||||
module.exports.watcher = {
|
|
||||||
realSubmit: () => {
|
|
||||||
return {
|
|
||||||
then: () => {}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
check: () => {},
|
|
||||||
save: () => {
|
|
||||||
return {
|
|
||||||
then: () => {}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
notifySaved: () => {}
|
|
||||||
};
|
|
|
@ -25,12 +25,15 @@ export default class Dialog extends Component {
|
||||||
}, null, 'buttons');
|
}, null, 'buttons');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set body(value) {
|
set body(value) {
|
||||||
this.element.querySelector('.body').appendChild(value);
|
this.element.querySelector('.body').appendChild(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
set buttons(value) {
|
set buttons(value) {
|
||||||
this.element.querySelector('.buttons').appendChild(value);
|
this.element.querySelector('.buttons').appendChild(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the dialog to the user.
|
* Displays the dialog to the user.
|
||||||
*/
|
*/
|
||||||
|
@ -48,6 +51,7 @@ export default class Dialog extends Component {
|
||||||
let firstFocusable = this.element.querySelector('input, textarea');
|
let firstFocusable = this.element.querySelector('input, textarea');
|
||||||
if (firstFocusable) firstFocusable.focus();
|
if (firstFocusable) firstFocusable.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hides the dialog calling the response handler.
|
* Hides the dialog calling the response handler.
|
||||||
*/
|
*/
|
||||||
|
@ -55,6 +59,7 @@ export default class Dialog extends Component {
|
||||||
this.fireResponse();
|
this.fireResponse();
|
||||||
this.realHide();
|
this.realHide();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls the response handler.
|
* Calls the response handler.
|
||||||
*
|
*
|
||||||
|
@ -67,15 +72,16 @@ export default class Dialog extends Component {
|
||||||
cancel = this.onResponse({response: response});
|
cancel = this.onResponse({response: response});
|
||||||
return cancel;
|
return cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
realHide() {
|
realHide() {
|
||||||
if (!this.shown) return;
|
if (!this.shown) return;
|
||||||
this.element.style.display = 'none';
|
this.element.style.display = 'none';
|
||||||
this.document.removeEventListener('keydown', this.keyDownHandler);
|
this.document.removeEventListener('keydown', this.keyDownHandler);
|
||||||
this.lastEvent = null;
|
this.lastEvent = null;
|
||||||
this.shown = false;
|
this.shown = false;
|
||||||
this.transitionTimeout =
|
this.transitionTimeout = setTimeout(() => this.$element.removeClass('shown'), 30);
|
||||||
setTimeout(() => this.$element.removeClass('shown'), 30);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onButtonClick(event) {
|
onButtonClick(event) {
|
||||||
let buttons = this.element.querySelector('.buttons');
|
let buttons = this.element.querySelector('.buttons');
|
||||||
let tplButtons = buttons.querySelector('tpl-buttons');
|
let tplButtons = buttons.querySelector('tpl-buttons');
|
||||||
|
@ -89,17 +95,21 @@ export default class Dialog extends Component {
|
||||||
let cancel = this.fireResponse(response);
|
let cancel = this.fireResponse(response);
|
||||||
if (cancel !== false) this.realHide();
|
if (cancel !== false) this.realHide();
|
||||||
}
|
}
|
||||||
|
|
||||||
onDialogMouseDown(event) {
|
onDialogMouseDown(event) {
|
||||||
this.lastEvent = event;
|
this.lastEvent = event;
|
||||||
}
|
}
|
||||||
|
|
||||||
onBackgroundMouseDown(event) {
|
onBackgroundMouseDown(event) {
|
||||||
if (event != this.lastEvent)
|
if (event != this.lastEvent)
|
||||||
this.hide();
|
this.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
onkeyDown(event) {
|
onkeyDown(event) {
|
||||||
if (event.keyCode == 27) // Esc
|
if (event.keyCode == 27) // Esc
|
||||||
this.hide();
|
this.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
$onDestroy() {
|
$onDestroy() {
|
||||||
clearTimeout(this.transitionTimeout);
|
clearTimeout(this.transitionTimeout);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,44 +10,68 @@ describe('Component vnDialog', () => {
|
||||||
beforeEach(angular.mock.inject(_$componentController_ => {
|
beforeEach(angular.mock.inject(_$componentController_ => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$element = angular.element('<vn-dialog></vn-dialog>');
|
$element = angular.element('<vn-dialog></vn-dialog>');
|
||||||
controller = $componentController('vnDialog', {$element: $element, $transclude: null});
|
controller = $componentController('vnDialog', {$element, $transclude: null});
|
||||||
|
controller.onOpen = jasmine.createSpy('onOpen');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('show()', () => {
|
describe('show()', () => {
|
||||||
it(`should handle escape keypress event, define element.style.display to not none and call onOpen function`, () => {
|
it(`should do nothing if controller.shown is defined`, () => {
|
||||||
window.innerHeight = 600;
|
controller.element = {style: {display: 'none'}};
|
||||||
window.innerWidth = 800;
|
controller.shown = true;
|
||||||
controller.dialog = {style: {display: 'none'}};
|
|
||||||
controller.onOpen = () => {};
|
|
||||||
spyOn(controller, 'onOpen');
|
|
||||||
controller.show();
|
controller.show();
|
||||||
|
|
||||||
expect(controller.element.style.display).not.toEqual('none');
|
expect(controller.element.style.display).toEqual('none');
|
||||||
|
expect(controller.onOpen).not.toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should set shown on the controller, set style.display on the element and call onOpen()`, () => {
|
||||||
|
controller.show();
|
||||||
|
|
||||||
|
expect(controller.element.style.display).toEqual('flex');
|
||||||
|
expect(controller.shown).toBeTruthy();
|
||||||
expect(controller.onOpen).toHaveBeenCalledWith();
|
expect(controller.onOpen).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('hide()', () => {
|
describe('hide()', () => {
|
||||||
it(`should call onResponse()`, () => {
|
describe('fireResponse()', () => {
|
||||||
controller.onResponse = () => {};
|
it(`should call onResponse() if it's defined in the controller`, () => {
|
||||||
spyOn(controller, 'onResponse');
|
controller.onResponse = () => {};
|
||||||
controller.hide();
|
spyOn(controller, 'onResponse');
|
||||||
|
controller.hide();
|
||||||
|
|
||||||
expect(controller.onResponse).toHaveBeenCalled();
|
expect(controller.onResponse).toHaveBeenCalledWith(jasmine.any(Object));
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should call onResponse() with a response`, () => {
|
||||||
|
let responseRes;
|
||||||
|
controller.onResponse = response => {
|
||||||
|
responseRes = response;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
let responseRet = controller.fireResponse('answer');
|
||||||
|
|
||||||
|
expect(responseRes).toEqual({response: 'answer'});
|
||||||
|
expect(responseRet).toEqual(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe('fireResponse()', () => {
|
describe('realHide()', () => {
|
||||||
it(`should call onResponse()`, () => {
|
it(`should do nothing if controller.shown is not defined`, () => {
|
||||||
let responseRes;
|
controller.element = {style: {display: 'not none'}};
|
||||||
controller.onResponse = response => {
|
controller.hide();
|
||||||
responseRes = response;
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
let responseRet = controller.fireResponse('answer');
|
|
||||||
|
|
||||||
expect(responseRes).toEqual({response: 'answer'});
|
expect(controller.element.style.display).toEqual('not none');
|
||||||
expect(responseRet).toEqual(false);
|
});
|
||||||
|
|
||||||
|
it(`should set lastEvent, shown and element.style.display to their expected values`, () => {
|
||||||
|
controller.shown = true;
|
||||||
|
controller.hide();
|
||||||
|
|
||||||
|
expect(controller.lastEvent).toBeFalsy();
|
||||||
|
expect(controller.shown).toBeFalsy();
|
||||||
|
expect(controller.element.style.display).toEqual('none');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,10 +11,9 @@ describe('Component vnPopover', () => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_, _$document_) => {
|
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_, _$timeout_) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$timeout = _$timeout_;
|
$timeout = _$timeout_;
|
||||||
$timeout.cancel = () => {};
|
|
||||||
$element = angular.element(`<div class="shown"></div>`);
|
$element = angular.element(`<div class="shown"></div>`);
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
_$httpBackend_.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
_$httpBackend_.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
|
|
|
@ -132,7 +132,7 @@ export default class CrudModel extends ModelProxy {
|
||||||
|
|
||||||
let url = this.saveUrl ? this.saveUrl : `${this.url}/crud`;
|
let url = this.saveUrl ? this.saveUrl : `${this.url}/crud`;
|
||||||
return this.$http.post(url, changes)
|
return this.$http.post(url, changes)
|
||||||
.then(() => this.resetChanges);
|
.then(() => this.resetChanges());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CrudModel.$inject = ['$http', '$q'];
|
CrudModel.$inject = ['$http', '$q'];
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
translate-attr="{title: 'Clear'}"
|
translate-attr="{title: 'Clear'}"
|
||||||
ng-show="!$ctrl.disabled
|
ng-show="!$ctrl.disabled
|
||||||
&& $ctrl.hasValue
|
&& $ctrl.hasValue
|
||||||
&& ($ctrl.hasFocus)
|
|
||||||
&& !$ctrl.unclearable"
|
&& !$ctrl.unclearable"
|
||||||
ng-click="$ctrl.clear()">
|
ng-click="$ctrl.clear()">
|
||||||
clear
|
clear
|
||||||
|
|
|
@ -180,17 +180,6 @@ export default class Watcher extends Component {
|
||||||
this.vnApp.showSuccess(this._.instant('Data saved!'));
|
this.vnApp.showSuccess(this._.instant('Data saved!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
writeData(json, resolve) {
|
|
||||||
Object.assign(this.data, json.data);
|
|
||||||
this.updateOriginalData();
|
|
||||||
resolve(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateOriginalData() {
|
|
||||||
this.orgData = this.copyInNewObject(this.data);
|
|
||||||
this.setPristine();
|
|
||||||
}
|
|
||||||
|
|
||||||
setPristine() {
|
setPristine() {
|
||||||
if (this.form) this.form.$setPristine();
|
if (this.form) this.form.$setPristine();
|
||||||
}
|
}
|
||||||
|
@ -199,24 +188,6 @@ export default class Watcher extends Component {
|
||||||
if (this.form) this.form.$setDirty();
|
if (this.form) this.form.$setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
copyInNewObject(data) {
|
|
||||||
let newCopy = {};
|
|
||||||
if (data && typeof data === 'object') {
|
|
||||||
Object.keys(data).forEach(
|
|
||||||
val => {
|
|
||||||
if (!isFullEmpty(data[val])) {
|
|
||||||
if (typeof data[val] === 'object') {
|
|
||||||
newCopy[val] = this.copyInNewObject(data[val]);
|
|
||||||
} else {
|
|
||||||
newCopy[val] = data[val];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return newCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(transition) {
|
callback(transition) {
|
||||||
if (!this.state && this.dirty) {
|
if (!this.state && this.dirty) {
|
||||||
this.state = transition.to().name;
|
this.state = transition.to().name;
|
||||||
|
@ -236,6 +207,35 @@ export default class Watcher extends Component {
|
||||||
this.state = null;
|
this.state = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
writeData(json, resolve) {
|
||||||
|
Object.assign(this.data, json.data);
|
||||||
|
this.updateOriginalData();
|
||||||
|
resolve(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOriginalData() {
|
||||||
|
this.orgData = this.copyInNewObject(this.data);
|
||||||
|
this.setPristine();
|
||||||
|
}
|
||||||
|
|
||||||
|
copyInNewObject(data) {
|
||||||
|
let newCopy = {};
|
||||||
|
if (data && typeof data === 'object') {
|
||||||
|
Object.keys(data).forEach(
|
||||||
|
val => {
|
||||||
|
if (!isFullEmpty(data[val])) {
|
||||||
|
if (typeof data[val] === 'object') {
|
||||||
|
newCopy[val] = this.copyInNewObject(data[val]);
|
||||||
|
} else {
|
||||||
|
newCopy[val] = data[val];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return newCopy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnApp', '$translate', '$attrs', '$q'];
|
Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnApp', '$translate', '$attrs', '$q'];
|
||||||
|
|
||||||
|
|
|
@ -9,4 +9,4 @@ import './zoom-image';
|
||||||
import './visible-by';
|
import './visible-by';
|
||||||
import './bind';
|
import './bind';
|
||||||
import './repeat-last';
|
import './repeat-last';
|
||||||
import './title';
|
import './title';
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import splitingRegister from './spliting-register';
|
import splitingRegister from './spliting-register';
|
||||||
|
|
||||||
factory.$inject = ['$http', '$window', '$ocLazyLoad', '$translatePartialLoader', '$translate'];
|
factory.$inject = ['$http', '$window', '$ocLazyLoad', '$translatePartialLoader', '$translate', '$q'];
|
||||||
export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $translate) {
|
export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $translate, $q) {
|
||||||
class ModuleLoader {
|
class ModuleLoader {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._loaded = {};
|
this._loaded = {};
|
||||||
|
@ -15,7 +15,7 @@ export function factory($http, $window, $ocLazyLoad, $translatePartialLoader, $t
|
||||||
if (loaded[moduleName] instanceof Promise)
|
if (loaded[moduleName] instanceof Promise)
|
||||||
return loaded[moduleName];
|
return loaded[moduleName];
|
||||||
if (loaded[moduleName] === false)
|
if (loaded[moduleName] === false)
|
||||||
return Promise.reject(
|
return $q.reject(
|
||||||
new Error(`Module dependency loop detected: ${moduleName}`));
|
new Error(`Module dependency loop detected: ${moduleName}`));
|
||||||
|
|
||||||
loaded[moduleName] = false;
|
loaded[moduleName] = false;
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
module.exports.crudModel = {
|
||||||
|
data: [],
|
||||||
|
insert: () => {
|
||||||
|
return new Promise(accept => {
|
||||||
|
accept();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
remove: () => {
|
||||||
|
return new Promise(accept => {
|
||||||
|
accept();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
save: () => {
|
||||||
|
return new Promise(accept => {
|
||||||
|
accept();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
refresh: () => {}
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
module.exports.watcher = {
|
||||||
|
realSubmit: () => {
|
||||||
|
return new Promise(accept => {
|
||||||
|
accept();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
check: () => {},
|
||||||
|
notifySaved: () => {},
|
||||||
|
setDirty: () => {},
|
||||||
|
setPristine: () => {}
|
||||||
|
};
|
|
@ -1,11 +1,19 @@
|
||||||
|
<vn-crud-model
|
||||||
|
vn-id="model"
|
||||||
|
url="/item/api/ItemBarcodes"
|
||||||
|
fields="['id', 'itemFk', 'code']"
|
||||||
|
link="{itemFk: $ctrl.$stateParams.id}"
|
||||||
|
data="barcodes">
|
||||||
|
</vn-crud-model>
|
||||||
<vn-watcher
|
<vn-watcher
|
||||||
vn-id="watcher"
|
vn-id="watcher"
|
||||||
|
data="barcodes"
|
||||||
form="form">
|
form="form">
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
<form name="form" ng-submit="$ctrl.submit()">
|
<form name="form" ng-submit="$ctrl.onSubmit()">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Barcodes</vn-title>
|
<vn-title>Barcodes</vn-title>
|
||||||
<vn-horizontal ng-repeat="barcode in $ctrl.barcodes track by $index">
|
<vn-horizontal ng-repeat="barcode in barcodes track by $index">
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-three
|
vn-three
|
||||||
label="Code"
|
label="Code"
|
||||||
|
@ -13,15 +21,17 @@
|
||||||
vn-acl="buyer, replenisher"
|
vn-acl="buyer, replenisher"
|
||||||
vn-focus>
|
vn-focus>
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
|
<vn-none>
|
||||||
<vn-icon
|
<vn-icon
|
||||||
pad-medium-top
|
medium-grey
|
||||||
|
margin-medium-v
|
||||||
vn-acl="buyer,replenisher"
|
vn-acl="buyer,replenisher"
|
||||||
pointer
|
pointer
|
||||||
medium-grey
|
|
||||||
vn-tooltip="Remove barcode"
|
vn-tooltip="Remove barcode"
|
||||||
icon="remove_circle_outline"
|
icon="remove_circle_outline"
|
||||||
ng-click="$ctrl.removeBarcode($index)">
|
ng-click="model.remove($index)">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
|
</vn-none>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-one>
|
<vn-one>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
|
@ -29,7 +39,7 @@
|
||||||
vn-tooltip="Add barcode"
|
vn-tooltip="Add barcode"
|
||||||
vn-bind="+"
|
vn-bind="+"
|
||||||
icon="add_circle"
|
icon="add_circle"
|
||||||
ng-click="$ctrl.addBarcode()">
|
ng-click="model.insert()">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
|
|
|
@ -1,129 +1,21 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller {
|
||||||
constructor($state, $scope, $http, $q, $translate, vnApp) {
|
constructor($stateParams, $scope) {
|
||||||
this.$state = $state;
|
this.$stateParams = $stateParams;
|
||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
this.$http = $http;
|
|
||||||
this.$q = $q;
|
|
||||||
this.$translate = $translate;
|
|
||||||
this.vnApp = vnApp;
|
|
||||||
|
|
||||||
this.barcodes = [];
|
|
||||||
this.removedBarcodes = [];
|
|
||||||
this.oldBarcodes = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_setIconAdd() {
|
onSubmit() {
|
||||||
if (this.barcodes.length) {
|
this.$scope.watcher.check();
|
||||||
this.barcodes.map(element => {
|
this.$scope.model.save().then(() => {
|
||||||
element.showAddIcon = false;
|
this.$scope.watcher.notifySaved();
|
||||||
return true;
|
this.$scope.model.refresh();
|
||||||
});
|
|
||||||
this.barcodes[this.barcodes.length - 1].showAddIcon = true;
|
|
||||||
} else {
|
|
||||||
this.addBarcode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_setDirtyForm() {
|
|
||||||
if (this.$scope.form) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
addBarcode() {
|
|
||||||
this.barcodes.push({code: null, itemFk: this.$state.params.id, showAddIcon: true});
|
|
||||||
this._setIconAdd();
|
|
||||||
}
|
|
||||||
|
|
||||||
removeBarcode(index) {
|
|
||||||
let item = this.barcodes[index];
|
|
||||||
if (item) {
|
|
||||||
this.barcodes.splice(index, 1);
|
|
||||||
this._setIconAdd();
|
|
||||||
if (item.id) {
|
|
||||||
this.removedBarcodes.push(item.id);
|
|
||||||
this._setDirtyForm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
submit() {
|
|
||||||
let codes = [];
|
|
||||||
let repeatedBarcodes = false;
|
|
||||||
let canSubmit;
|
|
||||||
let barcodesObj = {
|
|
||||||
delete: this.removedBarcodes,
|
|
||||||
create: [],
|
|
||||||
update: []
|
|
||||||
};
|
|
||||||
for (let i = 0; i < this.barcodes.length; i++) {
|
|
||||||
let barcode = this.barcodes[i];
|
|
||||||
let isNewBarcode = barcode.id === undefined;
|
|
||||||
|
|
||||||
if (barcode.code && codes.indexOf(barcode.code) !== -1) {
|
|
||||||
repeatedBarcodes = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (barcode.code) codes.push(barcode.code);
|
|
||||||
|
|
||||||
if (isNewBarcode && barcode.code) {
|
|
||||||
barcodesObj.create.push(barcode);
|
|
||||||
} else if (!isNewBarcode && !this._equalBarcodes(this.oldBarcodes[barcode.id], barcode)) {
|
|
||||||
barcodesObj.update.push(barcode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (repeatedBarcodes) {
|
|
||||||
return this.vnApp.showError(this.$translate.instant('The barcode must be unique'));
|
|
||||||
}
|
|
||||||
|
|
||||||
canSubmit = barcodesObj.update.length > 0 || barcodesObj.create.length > 0 || barcodesObj.delete.length > 0;
|
|
||||||
|
|
||||||
if (canSubmit) {
|
|
||||||
return this.$http.post(`/item/api/ItemBarcodes/crudItemBarcodes`, barcodesObj).then(() => {
|
|
||||||
this.getBarcodes();
|
|
||||||
this._unsetDirtyForm();
|
|
||||||
this.$scope.watcher.notifySaved();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.vnApp.showError(this.$translate.instant('No changes to save'));
|
|
||||||
}
|
|
||||||
|
|
||||||
setOldBarcodes(response) {
|
|
||||||
this._setIconAdd();
|
|
||||||
response.data.forEach(barcode => {
|
|
||||||
this.oldBarcodes[barcode.id] = Object.assign({}, barcode);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getBarcodes() {
|
|
||||||
let filter = {
|
|
||||||
where: {itemFk: this.$state.params.id}
|
|
||||||
};
|
|
||||||
this.$http.get(`/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`).then(response => {
|
|
||||||
this.barcodes = response.data;
|
|
||||||
this.setOldBarcodes(response);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$onInit() {
|
|
||||||
this.getBarcodes();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$state', '$scope', '$http', '$q', '$translate', 'vnApp'];
|
Controller.$inject = ['$stateParams', '$scope'];
|
||||||
|
|
||||||
ngModule.component('vnItemBarcode', {
|
ngModule.component('vnItemBarcode', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Item', () => {
|
|
||||||
describe('Component vnItemBarcode', () => {
|
|
||||||
let $componentController;
|
|
||||||
let $state;
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
angular.mock.module('item');
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
|
||||||
$componentController = _$componentController_;
|
|
||||||
$state = _$state_;
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
|
||||||
$state.params.id = '1';
|
|
||||||
controller = $componentController('vnItemBarcode', {$state: $state});
|
|
||||||
controller.$scope.watcher = {
|
|
||||||
notifySaved: () => {}
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('add / remove barcode()', () => {
|
|
||||||
it('should add one empty barcode into controller barcodes collection and call _setIconAdd()', () => {
|
|
||||||
controller.barcodes = [];
|
|
||||||
spyOn(controller, '_setIconAdd').and.callThrough();
|
|
||||||
controller.addBarcode();
|
|
||||||
|
|
||||||
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
|
||||||
expect(controller.barcodes.length).toEqual(1);
|
|
||||||
expect(controller.barcodes[0].id).toBe(undefined);
|
|
||||||
expect(controller.barcodes[0].showAddIcon).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove a barcode that occupies the position in the index given and call _setIconAdd()', () => {
|
|
||||||
let index = 2;
|
|
||||||
controller.barcodes = [
|
|
||||||
{id: 1, code: '1111', showAddIcon: false},
|
|
||||||
{id: 2, code: '2222', showAddIcon: false},
|
|
||||||
{id: 3, code: '3333', showAddIcon: true}
|
|
||||||
];
|
|
||||||
|
|
||||||
spyOn(controller, '_setIconAdd').and.callThrough();
|
|
||||||
|
|
||||||
controller.removeBarcode(index);
|
|
||||||
|
|
||||||
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
|
||||||
expect(controller.barcodes.length).toEqual(2);
|
|
||||||
expect(controller.barcodes[0].showAddIcon).toBeFalsy();
|
|
||||||
expect(controller.barcodes[1].showAddIcon).toBeTruthy();
|
|
||||||
expect(controller.barcodes[index]).toBe(undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('_equalBarcodes()', () => {
|
|
||||||
it('should return true if two barcodes are equals independent of control attributes', () => {
|
|
||||||
let code1 = {id: 1, code: '1111', showAddIcon: true};
|
|
||||||
let code2 = {id: 1, code: '1111', showAddIcon: false};
|
|
||||||
let equals = controller._equalBarcodes(code2, code1);
|
|
||||||
|
|
||||||
expect(equals).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false if two barcodes aint equals independent of control attributes', () => {
|
|
||||||
let code1 = {id: 1, code: '1111', showAddIcon: true};
|
|
||||||
let code2 = {id: 1, code: '2222', showAddIcon: true};
|
|
||||||
let equals = controller._equalBarcodes(code2, code1);
|
|
||||||
|
|
||||||
expect(equals).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getBarcodes()', () => {
|
|
||||||
it('should perform a GET query to receive the item barcodes', () => {
|
|
||||||
let filter = {
|
|
||||||
where: {itemFk: '1'}
|
|
||||||
};
|
|
||||||
let res = [{id: 1, code: '1111'}];
|
|
||||||
$httpBackend.when('GET', `/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`).respond(res);
|
|
||||||
$httpBackend.expectGET(`/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`);
|
|
||||||
controller.getBarcodes();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('submit()', () => {
|
|
||||||
it("should return an error message 'The barcode must be unique' when the code isnt unique", () => {
|
|
||||||
spyOn(controller.vnApp, 'showError').and.callThrough();
|
|
||||||
controller.barcodes = [
|
|
||||||
{code: 123454, itemFk: 1, id: 1},
|
|
||||||
{code: 123454, itemFk: 1}
|
|
||||||
];
|
|
||||||
controller.oldBarcodes = {1: {id: 1, code: 123454, itemFk: 1}};
|
|
||||||
controller.submit();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith('The barcode must be unique');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should perfom a query to delete barcodes", () => {
|
|
||||||
controller.removedBarcodes = [1, 2, 3];
|
|
||||||
|
|
||||||
$httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{code: 123454, itemFk: 1, id: 1}]);
|
|
||||||
$httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!');
|
|
||||||
$httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`);
|
|
||||||
controller.submit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should perfom a query to update barcodes", () => {
|
|
||||||
controller.barcodes = [{code: 2222, itemFk: 1, id: 1}];
|
|
||||||
controller.oldBarcodes = {1: {id: 1, code: 1111, itemFk: 1}};
|
|
||||||
|
|
||||||
$httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{}]);
|
|
||||||
$httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!');
|
|
||||||
$httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`);
|
|
||||||
controller.submit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should perfom a query to create new barcode", () => {
|
|
||||||
controller.barcodes = [{code: 1111, itemFk: 1}];
|
|
||||||
|
|
||||||
$httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{}]);
|
|
||||||
$httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!');
|
|
||||||
$httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`);
|
|
||||||
controller.submit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return a message 'No changes to save' when there are no changes to apply", () => {
|
|
||||||
spyOn(controller.vnApp, 'showError').and.callThrough();
|
|
||||||
controller.oldBarcodes = [
|
|
||||||
{code: 1, itemFk: 1, id: 1},
|
|
||||||
{code: 2, itemFk: 1, id: 2}
|
|
||||||
];
|
|
||||||
controller.barcodes = [];
|
|
||||||
controller.submit();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith('No changes to save');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -37,10 +37,11 @@
|
||||||
<vn-tr ng-class="{'warning': $ctrl.isToday(sale.date)}"
|
<vn-tr ng-class="{'warning': $ctrl.isToday(sale.date)}"
|
||||||
ng-repeat="sale in sales" vn-repeat-last on-last="$ctrl.scrollToActive()">
|
ng-repeat="sale in sales" vn-repeat-last on-last="$ctrl.scrollToActive()">
|
||||||
<vn-td>{{::sale.date | date:'dd/MM/yyyy HH:mm' }}</vn-td>
|
<vn-td>{{::sale.date | date:'dd/MM/yyyy HH:mm' }}</vn-td>
|
||||||
<vn-td number>{{::sale.origin | dashIfEmpty}}</vn-td>
|
<vn-td ng-click="$ctrl.showDescriptor($event, sale)" pointer number class="link">
|
||||||
|
{{::sale.origin | dashIfEmpty}}</vn-td>
|
||||||
<vn-td>{{::sale.stateName | dashIfEmpty}}</vn-td>
|
<vn-td>{{::sale.stateName | dashIfEmpty}}</vn-td>
|
||||||
<vn-td>{{::sale.reference | dashIfEmpty}}</vn-td>
|
<vn-td>{{::sale.reference | dashIfEmpty}}</vn-td>
|
||||||
<vn-td>{{sale.name | dashIfEmpty}}</vn-td>
|
<vn-td >{{sale.name | dashIfEmpty}}</vn-td>
|
||||||
<vn-td number>{{::sale.in | dashIfEmpty}}</vn-td>
|
<vn-td number>{{::sale.in | dashIfEmpty}}</vn-td>
|
||||||
<vn-td number>{{::sale.out | dashIfEmpty}}</vn-td>
|
<vn-td number>{{::sale.out | dashIfEmpty}}</vn-td>
|
||||||
<vn-td number><span class="balance">{{::sale.balance | dashIfEmpty}}</span></vn-td>
|
<vn-td number><span class="balance">{{::sale.balance | dashIfEmpty}}</span></vn-td>
|
||||||
|
@ -53,3 +54,4 @@
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
|
<vn-ticket-descriptor-popover vn-id="descriptor"></vn-ticket-descriptor-popover>
|
||||||
|
|
|
@ -110,6 +110,20 @@ class Controller {
|
||||||
if (!(today - comparedDate))
|
if (!(today - comparedDate))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showDescriptor(event, sale) {
|
||||||
|
if (!sale.isTicket) return;
|
||||||
|
|
||||||
|
this.$scope.descriptor.ticketFk = sale.origin;
|
||||||
|
this.$scope.descriptor.parent = event.target;
|
||||||
|
this.$scope.descriptor.show();
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
onDescriptorLoad() {
|
||||||
|
this.$scope.popover.relocate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$scope', '$http', '$state', '$window'];
|
Controller.$inject = ['$scope', '$http', '$state', '$window'];
|
||||||
|
|
|
@ -7,6 +7,9 @@ import './diary';
|
||||||
import './create';
|
import './create';
|
||||||
import './card';
|
import './card';
|
||||||
import './descriptor';
|
import './descriptor';
|
||||||
|
import './descriptor-popover';
|
||||||
|
import './ticket-descriptor';
|
||||||
|
import './ticket-descriptor-popover';
|
||||||
import './data';
|
import './data';
|
||||||
import './tags';
|
import './tags';
|
||||||
import './tax';
|
import './tax';
|
||||||
|
@ -16,4 +19,4 @@ import './niche';
|
||||||
import './botanical';
|
import './botanical';
|
||||||
import './barcode';
|
import './barcode';
|
||||||
import './summary';
|
import './summary';
|
||||||
import './descriptor-popover';
|
|
||||||
|
|
|
@ -1,48 +1,46 @@
|
||||||
|
<vn-crud-model
|
||||||
|
vn-id="model"
|
||||||
|
url="/item/api/ItemNiches"
|
||||||
|
fields="['id', 'itemFk', 'warehouseFk', 'code']"
|
||||||
|
link="{itemFk: $ctrl.$stateParams.id}"
|
||||||
|
data="niches">
|
||||||
|
</vn-crud-model>
|
||||||
<vn-watcher
|
<vn-watcher
|
||||||
vn-id="watcher"
|
vn-id="watcher"
|
||||||
data="$ctrl.item"
|
data="niches"
|
||||||
form="form">
|
form="form">
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
<form name="form" ng-submit="$ctrl.submit()">
|
<form name="form" ng-submit="$ctrl.onSubmit()">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Niches</vn-title>
|
<vn-title>Niches</vn-title>
|
||||||
<vn-horizontal ng-repeat="itemNiche in $ctrl.niches track by $index">
|
<vn-horizontal ng-repeat="niche in niches track by $index">
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
ng-if="!itemNiche.id"
|
disabled="niche.id != null"
|
||||||
vn-one
|
url="/item/api/Warehouses"
|
||||||
vn-focus
|
|
||||||
data="$ctrl.warehouses"
|
|
||||||
show-field="name"
|
show-field="name"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
initial-data="itemNiche.warehouse"
|
field="niche.warehouseFk"
|
||||||
field="itemNiche.warehouseFk"
|
|
||||||
label="Warehouse"
|
label="Warehouse"
|
||||||
vn-acl="buyer,replenisher">
|
vn-acl="buyer,replenisher" vn-one vn-focus>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-textfield
|
|
||||||
ng-if="itemNiche.id"
|
|
||||||
vn-focus
|
|
||||||
vn-one
|
|
||||||
label="Warehouse"
|
|
||||||
model="itemNiche.warehouse.name"
|
|
||||||
disabled="true">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-three
|
vn-three
|
||||||
label="Code"
|
label="Code"
|
||||||
model="itemNiche.code"
|
model="niche.code"
|
||||||
rule="itemNiche.code"
|
rule="itemNiche.code"
|
||||||
vn-acl="buyer,replenisher">
|
vn-acl="buyer,replenisher">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-icon
|
<vn-none>
|
||||||
pad-medium-top
|
<vn-icon
|
||||||
vn-acl="buyer,replenisher"
|
medium-grey
|
||||||
pointer
|
margin-medium-v
|
||||||
medium-grey
|
vn-acl="buyer,replenisher"
|
||||||
vn-tooltip="Remove niche"
|
pointer
|
||||||
icon="remove_circle_outline"
|
vn-tooltip="Remove niche"
|
||||||
ng-click="$ctrl.removeNiche($index)">
|
icon="remove_circle_outline"
|
||||||
</vn-icon>
|
ng-click="model.remove($index)">
|
||||||
|
</vn-icon>
|
||||||
|
</vn-none>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-one>
|
<vn-one>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
|
@ -50,7 +48,7 @@
|
||||||
vn-tooltip="Add niche"
|
vn-tooltip="Add niche"
|
||||||
vn-bind="+"
|
vn-bind="+"
|
||||||
icon="add_circle"
|
icon="add_circle"
|
||||||
ng-click="$ctrl.addNiche()">
|
ng-click="model.insert()">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
|
|
|
@ -1,148 +1,21 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller {
|
||||||
constructor($stateParams, $scope, $http, $translate, vnApp) {
|
constructor($stateParams, $scope) {
|
||||||
this.params = $stateParams;
|
this.$stateParams = $stateParams;
|
||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
this.$http = $http;
|
|
||||||
this.$translate = $translate;
|
|
||||||
this.vnApp = vnApp;
|
|
||||||
|
|
||||||
this.warehouses = [];
|
|
||||||
this.niches = [];
|
|
||||||
this.removedNiches = [];
|
|
||||||
this.oldNiches = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
onSubmit() {
|
||||||
this.getNiches();
|
this.$scope.watcher.check();
|
||||||
this.getWarehouses();
|
this.$scope.model.save().then(() => {
|
||||||
}
|
this.$scope.watcher.notifySaved();
|
||||||
|
this.$scope.model.refresh();
|
||||||
_setIconAdd() {
|
|
||||||
if (this.niches.length) {
|
|
||||||
this.niches.map(element => {
|
|
||||||
element.showAddIcon = false;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
this.niches[this.niches.length - 1].showAddIcon = true;
|
|
||||||
} else {
|
|
||||||
this.addNiche();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_setDirtyForm() {
|
|
||||||
if (this.$scope.form) {
|
|
||||||
this.$scope.form.$setDirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_unsetDirtyForm() {
|
|
||||||
if (this.$scope.form) {
|
|
||||||
this.$scope.form.$setPristine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addNiche() {
|
|
||||||
this.niches.push({code: null, itemFk: this.params.id, showAddIcon: true});
|
|
||||||
this._setIconAdd();
|
|
||||||
}
|
|
||||||
|
|
||||||
removeNiche(index) {
|
|
||||||
let item = this.niches[index];
|
|
||||||
if (item) {
|
|
||||||
this.niches.splice(index, 1);
|
|
||||||
this._setIconAdd();
|
|
||||||
if (item.id) {
|
|
||||||
this.removedNiches.push(item.id);
|
|
||||||
this._setDirtyForm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_equalNiches(oldNiche, newNiche) {
|
|
||||||
return oldNiche.id === newNiche.id && oldNiche.code === newNiche.code && oldNiche.warehouseFk === newNiche.warehouseFk;
|
|
||||||
}
|
|
||||||
|
|
||||||
setOldNiches(response) {
|
|
||||||
this._setIconAdd();
|
|
||||||
response.data.forEach(niche => {
|
|
||||||
this.oldNiches[niche.id] = Object.assign({}, niche);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getNiches() {
|
|
||||||
let filter = {
|
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getWarehouse(id, warehouses) {
|
|
||||||
return warehouses.find(warehouse => warehouse.id === id);
|
|
||||||
}
|
|
||||||
|
|
||||||
getWarehouses() {
|
|
||||||
this.$http.get(`/item/api/Warehouses`).then(response => {
|
|
||||||
this.warehouses = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
submit() {
|
|
||||||
let warehousesDefined = [];
|
|
||||||
let repeatedWarehouse = false;
|
|
||||||
let canSubmit;
|
|
||||||
let nichesObj = {
|
|
||||||
delete: this.removedNiches,
|
|
||||||
create: [],
|
|
||||||
update: []
|
|
||||||
};
|
|
||||||
|
|
||||||
this.niches.forEach(niche => {
|
|
||||||
let isNewNiche = !niche.id;
|
|
||||||
|
|
||||||
if (warehousesDefined.indexOf(niche.warehouseFk) !== -1) {
|
|
||||||
repeatedWarehouse = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
warehousesDefined.push(niche.warehouseFk);
|
|
||||||
|
|
||||||
if (isNewNiche) {
|
|
||||||
nichesObj.create.push(niche);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isNewNiche && !this._equalNiches(this.oldNiches[niche.id], niche)) {
|
|
||||||
nichesObj.update.push(niche);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.$scope.form.$invalid) {
|
|
||||||
return this.vnApp.showError(this.$translate.instant('Some fields are invalid'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (repeatedWarehouse) {
|
|
||||||
return this.vnApp.showError(this.$translate.instant('The niche must be unique'));
|
|
||||||
}
|
|
||||||
|
|
||||||
canSubmit = nichesObj.update.length > 0 || nichesObj.create.length > 0 || nichesObj.delete.length > 0;
|
|
||||||
|
|
||||||
if (canSubmit) {
|
|
||||||
return this.$http.post(`/item/api/ItemNiches/crudItemNiches`, nichesObj).then(() => {
|
|
||||||
this.getNiches();
|
|
||||||
this._unsetDirtyForm();
|
|
||||||
this.$scope.watcher.notifySaved();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.vnApp.showError(this.$translate.instant('No changes to save'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp'];
|
Controller.$inject = ['$stateParams', '$scope'];
|
||||||
|
|
||||||
ngModule.component('vnItemNiche', {
|
ngModule.component('vnItemNiche', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -1,159 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Item', () => {
|
|
||||||
describe('Component vnItemNiche', () => {
|
|
||||||
let $componentController;
|
|
||||||
let $state;
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
angular.mock.module('item');
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
|
||||||
$componentController = _$componentController_;
|
|
||||||
$state = _$state_;
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
|
||||||
controller = $componentController('vnItemNiche', {$state: $state});
|
|
||||||
controller.$scope.watcher = {
|
|
||||||
notifySaved: () => {}
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('add / remove niche', () => {
|
|
||||||
it('should add one empty niche into controller niches collection and call _setIconAdd()', () => {
|
|
||||||
controller.niches = [];
|
|
||||||
spyOn(controller, '_setIconAdd').and.callThrough();
|
|
||||||
controller.addNiche();
|
|
||||||
|
|
||||||
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
|
||||||
expect(controller.niches.length).toEqual(1);
|
|
||||||
expect(controller.niches[0].id).toBe(undefined);
|
|
||||||
expect(controller.niches[0].showAddIcon).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove a niche that occupies the position in the index given and call _setIconAdd()', () => {
|
|
||||||
let index = 2;
|
|
||||||
controller.niches = [
|
|
||||||
{id: 1, warehouseFk: 1, code: '1111', showAddIcon: false},
|
|
||||||
{id: 2, warehouseFk: 2, code: '2222', showAddIcon: false},
|
|
||||||
{id: 3, warehouseFk: 3, code: '3333', showAddIcon: true}
|
|
||||||
];
|
|
||||||
|
|
||||||
spyOn(controller, '_setIconAdd').and.callThrough();
|
|
||||||
|
|
||||||
controller.removeNiche(index);
|
|
||||||
|
|
||||||
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
|
||||||
expect(controller.niches.length).toEqual(2);
|
|
||||||
expect(controller.niches[0].showAddIcon).toBeFalsy();
|
|
||||||
expect(controller.niches[1].showAddIcon).toBeTruthy();
|
|
||||||
expect(controller.niches[index]).toBe(undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('_equalNiches()', () => {
|
|
||||||
it('should return true if two niches are equals independent of control attributes', () => {
|
|
||||||
let niche1 = {id: 1, warehouseFk: 1, code: '1111', showAddIcon: true};
|
|
||||||
let niche2 = {id: 1, warehouseFk: 1, code: '1111', showAddIcon: false};
|
|
||||||
let equals = controller._equalNiches(niche2, niche1);
|
|
||||||
|
|
||||||
expect(equals).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false if two niches aint equals independent of control attributes', () => {
|
|
||||||
let niche1 = {id: 1, warehouseFk: 1, code: '1111', showAddIcon: true};
|
|
||||||
let niche2 = {id: 1, warehouseFk: 1, code: '2222', showAddIcon: true};
|
|
||||||
let equals = controller._equalNiches(niche2, niche1);
|
|
||||||
|
|
||||||
expect(equals).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('get Niches / Warehouses', () => {
|
|
||||||
it('should perform a GET query to receive the item niches', () => {
|
|
||||||
let res = [{id: 1, warehouseFk: 1, code: '1111'}];
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond(res);
|
|
||||||
$httpBackend.expectGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`);
|
|
||||||
controller.getNiches();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should perform a GET query to receive the all warehouses', () => {
|
|
||||||
let res = [
|
|
||||||
{id: 1, warehouseFk: 1, name: 'warehouse one'},
|
|
||||||
{id: 2, warehouseFk: 2, name: 'warehouse two'}
|
|
||||||
];
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/Warehouses`).respond(res);
|
|
||||||
$httpBackend.expectGET(`/item/api/Warehouses`);
|
|
||||||
controller.getWarehouses();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('submit()', () => {
|
|
||||||
it("should return an error message 'The niche must be unique' when the niche warehouse isnt unique", () => {
|
|
||||||
controller.$scope.form = {};
|
|
||||||
spyOn(controller.vnApp, 'showError').and.callThrough();
|
|
||||||
controller.niches = [
|
|
||||||
{warehouseFk: 1, code: 123454, itemFk: 1, id: 1},
|
|
||||||
{warehouseFk: 1, code: 123454, itemFk: 1}
|
|
||||||
];
|
|
||||||
controller.oldNiches = {1: {warehouseFk: 1, id: 1, code: 123454, itemFk: 1}};
|
|
||||||
controller.submit();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith('The niche must be unique');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should perfom a query to delete niches", () => {
|
|
||||||
controller.$scope.form = {$setPristine: () => {}};
|
|
||||||
controller.oldNiches = {1: {id: 1, warehouseFk: 1, code: '1111'}};
|
|
||||||
controller.niches = [];
|
|
||||||
controller.removedNiches = [1];
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond([]);
|
|
||||||
$httpBackend.expectPOST(`/item/api/ItemNiches/crudItemNiches`).respond('ok!');
|
|
||||||
controller.submit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should perfom a query to update niches", () => {
|
|
||||||
controller.$scope.form = {$setPristine: () => {}};
|
|
||||||
controller.niches = [{id: 1, warehouseFk: 1, code: '2222'}];
|
|
||||||
controller.oldNiches = {1: {id: 1, warehouseFk: 1, code: '1111'}};
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond([]);
|
|
||||||
$httpBackend.expectPOST(`/item/api/ItemNiches/crudItemNiches`).respond('ok!');
|
|
||||||
controller.submit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should perfom a query to create new niche", () => {
|
|
||||||
controller.$scope.form = {$setPristine: () => {}};
|
|
||||||
controller.niches = [{warehouseFk: 1, code: 1111, itemFk: 1}];
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemNiches?filter={"where":{},"include":{"relation":"warehouse"}}`).respond([]);
|
|
||||||
$httpBackend.expectPOST(`/item/api/ItemNiches/crudItemNiches`).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, 'showError').and.callThrough();
|
|
||||||
controller.oldNiches = [
|
|
||||||
{warehouseFk: 1, code: 1, itemFk: 1, id: 1},
|
|
||||||
{warehouseFk: 2, code: 2, itemFk: 1, id: 2}
|
|
||||||
];
|
|
||||||
controller.niches = [];
|
|
||||||
controller.submit();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith('No changes to save');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,18 +1,27 @@
|
||||||
<mg-ajax path="/item/api/Tags" options="mgIndex as tags"></mg-ajax>
|
<vn-crud-model
|
||||||
|
vn-id="model"
|
||||||
|
url="/item/api/ItemTags"
|
||||||
|
fields="['id', 'itemFk', 'tagFk', 'value', 'priority']"
|
||||||
|
link="{itemFk: $ctrl.$stateParams.id}"
|
||||||
|
filter="{include: {relation: 'tag'}}"
|
||||||
|
order="priority ASC"
|
||||||
|
data="itemTags">
|
||||||
|
</vn-crud-model>
|
||||||
<vn-watcher
|
<vn-watcher
|
||||||
vn-id="watcher"
|
vn-id="watcher"
|
||||||
|
data="itemTags"
|
||||||
form="form">
|
form="form">
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
<form name="form" ng-submit="$ctrl.submit()">
|
<form name="form" ng-submit="$ctrl.onSubmit()">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Tags</vn-title>
|
<vn-title>Tags</vn-title>
|
||||||
<vn-horizontal ng-repeat="itemTag in $ctrl.tags">
|
<vn-horizontal ng-repeat="itemTag in itemTags">
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
vn-id="tag"
|
vn-id="tag"
|
||||||
vn-one
|
vn-one
|
||||||
initial-data="itemTag.tag"
|
|
||||||
field="itemTag.tagFk"
|
field="itemTag.tagFk"
|
||||||
data="tags.model"
|
url="/item/api/Tags"
|
||||||
|
select-fields="['id','name','isFree']"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
label="Tag"
|
label="Tag"
|
||||||
on-change="itemTag.value = null"
|
on-change="itemTag.value = null"
|
||||||
|
@ -54,7 +63,7 @@
|
||||||
margin-medium-v
|
margin-medium-v
|
||||||
vn-tooltip="Remove tag"
|
vn-tooltip="Remove tag"
|
||||||
icon="remove_circle_outline"
|
icon="remove_circle_outline"
|
||||||
ng-click="$ctrl.removeTag($index)"
|
ng-click="model.remove($index)"
|
||||||
tabindex="-1">
|
tabindex="-1">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-none>
|
</vn-none>
|
||||||
|
@ -64,7 +73,7 @@
|
||||||
vn-bind="+"
|
vn-bind="+"
|
||||||
vn-tooltip="Add tag"
|
vn-tooltip="Add tag"
|
||||||
icon="add_circle"
|
icon="add_circle"
|
||||||
ng-click="$ctrl.addTag()">
|
ng-click="$ctrl.add()">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
|
|
|
@ -1,63 +1,27 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor($stateParams, $scope, $http) {
|
constructor($stateParams, $scope) {
|
||||||
this.params = $stateParams;
|
this.$stateParams = $stateParams;
|
||||||
this.$ = $scope;
|
this.$scope = $scope;
|
||||||
this.$http = $http;
|
|
||||||
this.tags = [];
|
|
||||||
this.removedTags = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
add() {
|
||||||
this.getTags();
|
this.$scope.model.insert({
|
||||||
}
|
itemFk: this.$stateParams.id,
|
||||||
|
priority: this.getHighestPriority()
|
||||||
getTags() {
|
|
||||||
let filter = {
|
|
||||||
where: {itemFk: this.params.id},
|
|
||||||
order: 'priority ASC',
|
|
||||||
include: {relation: 'tag'}
|
|
||||||
};
|
|
||||||
this.$http.get(`/item/api/ItemTags?filter=${JSON.stringify(filter)}`).then(response => {
|
|
||||||
this.removedTags = [];
|
|
||||||
|
|
||||||
this.tags = response.data;
|
|
||||||
this.itemTags = JSON.parse(JSON.stringify(this.tags));
|
|
||||||
this.orgTags = {};
|
|
||||||
this.tags.forEach(tag => {
|
|
||||||
this.orgTags[tag.id] = Object.assign({}, tag);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$.form.$setPristine();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addTag() {
|
getHighestPriority() {
|
||||||
this.tags.push({
|
|
||||||
itemFk: this.params.id,
|
|
||||||
priority: this.getHighestPriority(this.tags)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getHighestPriority(tags) {
|
|
||||||
let max = 0;
|
let max = 0;
|
||||||
tags.forEach(tag => {
|
this.$scope.model.data.forEach(tag => {
|
||||||
if (tag.priority > max)
|
if (tag.priority > max)
|
||||||
max = tag.priority;
|
max = tag.priority;
|
||||||
});
|
});
|
||||||
return max + 1;
|
return max + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
removeTag(index) {
|
|
||||||
let item = this.tags[index];
|
|
||||||
this.tags.splice(index, 1);
|
|
||||||
if (item.id) {
|
|
||||||
this.removedTags.push(item.id);
|
|
||||||
this.$.form.$setDirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getSourceTable(selection) {
|
getSourceTable(selection) {
|
||||||
if (!selection || selection.isFree === true)
|
if (!selection || selection.isFree === true)
|
||||||
return null;
|
return null;
|
||||||
|
@ -70,43 +34,18 @@ class Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tagIsEqual(oldTag, newTag) {
|
onSubmit() {
|
||||||
return oldTag.tagFk === newTag.tagFk &&
|
this.$scope.watcher.check();
|
||||||
oldTag.value === newTag.value &&
|
this.$scope.model.save().then(() => {
|
||||||
oldTag.priority === newTag.priority;
|
this.$scope.watcher.notifySaved();
|
||||||
}
|
this.$scope.model.refresh();
|
||||||
|
|
||||||
submit() {
|
|
||||||
this.$.watcher.check();
|
|
||||||
|
|
||||||
let changes = {
|
|
||||||
delete: this.removedTags,
|
|
||||||
create: [],
|
|
||||||
update: []
|
|
||||||
};
|
|
||||||
this.tags.forEach(tag => {
|
|
||||||
if (!tag.id)
|
|
||||||
changes.create.push(tag);
|
|
||||||
else if (!this.tagIsEqual(this.orgTags[tag.id], tag)) {
|
|
||||||
let tagToUpdate = Object.assign({}, tag);
|
|
||||||
delete tagToUpdate.tag;
|
|
||||||
changes.update.push(tagToUpdate);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$http.post(`/item/api/ItemTags/crud`, changes).then(() => {
|
|
||||||
this.getTags();
|
|
||||||
this.$.watcher.notifySaved();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$stateParams', '$scope', '$http'];
|
Controller.$inject = ['$stateParams', '$scope'];
|
||||||
|
|
||||||
ngModule.component('vnItemTags', {
|
ngModule.component('vnItemTags', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Controller,
|
controller: Controller
|
||||||
bindings: {
|
|
||||||
itemTags: '='
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,71 +1,34 @@
|
||||||
import './index.js';
|
import './index.js';
|
||||||
|
import {crudModel} from '../../../helpers/crudModelHelper';
|
||||||
|
|
||||||
describe('Item', () => {
|
describe('Item', () => {
|
||||||
describe('Component vnItemTags', () => {
|
describe('Component vnItemTags', () => {
|
||||||
let $componentController;
|
let $componentController;
|
||||||
let $state;
|
let $scope;
|
||||||
let controller;
|
let controller;
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('item');
|
angular.mock.module('item');
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$state = _$state_;
|
$scope = $rootScope.$new();
|
||||||
$httpBackend = _$httpBackend_;
|
$scope.model = crudModel;
|
||||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
$scope.model.data = [{priority: 1}, {priority: 2}, {priority: 1}];
|
||||||
controller = $componentController('vnItemTags', {$state: $state});
|
controller = $componentController('vnItemTags', {$scope});
|
||||||
controller.$.form = {
|
|
||||||
$setPristine: () => {},
|
|
||||||
$dirty: true
|
|
||||||
};
|
|
||||||
controller.$.watcher = {
|
|
||||||
notifySaved: () => {},
|
|
||||||
check: () => {}
|
|
||||||
};
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('add / remove tags', () => {
|
|
||||||
it('should add one empty tag into controller tags collection', () => {
|
|
||||||
controller.tags = [];
|
|
||||||
controller.addTag();
|
|
||||||
|
|
||||||
expect(controller.tags.length).toEqual(1);
|
|
||||||
expect(controller.tags[0].id).toBe(undefined);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove a tag that occupies the position in the index', () => {
|
|
||||||
controller.$.form = {$setDirty: () => {}};
|
|
||||||
spyOn(controller.$.form, '$setDirty');
|
|
||||||
|
|
||||||
let index = 2;
|
|
||||||
controller.tags = [
|
|
||||||
{id: 1, typeFk: 1, value: '1111', showAddIcon: false},
|
|
||||||
{id: 2, typeFk: 2, value: '2222', showAddIcon: false},
|
|
||||||
{id: 3, typeFk: 3, value: '3333', showAddIcon: true}
|
|
||||||
];
|
|
||||||
|
|
||||||
controller.removeTag(index);
|
|
||||||
|
|
||||||
expect(controller.tags.length).toEqual(2);
|
|
||||||
expect(controller.tags[index]).toBe(undefined);
|
|
||||||
expect(controller.$.form.$setDirty).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getHighestPriority', () => {
|
describe('getHighestPriority', () => {
|
||||||
it('should return the highest priority value + 1 from the array', () => {
|
it('should return the highest priority value + 1 from the array', () => {
|
||||||
let tags = [{priority: 1}, {priority: 2}, {priority: 1}];
|
let result = controller.getHighestPriority();
|
||||||
let result = controller.getHighestPriority(tags);
|
|
||||||
|
|
||||||
expect(result).toEqual(3);
|
expect(result).toEqual(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 1 when there is no priority defined', () => {
|
it('should return 1 when there is no priority defined', () => {
|
||||||
let tags = [];
|
$scope.model.data = [];
|
||||||
let result = controller.getHighestPriority(tags);
|
let result = controller.getHighestPriority();
|
||||||
|
|
||||||
expect(result).toEqual(1);
|
expect(result).toEqual(1);
|
||||||
});
|
});
|
||||||
|
@ -93,100 +56,5 @@ describe('Item', () => {
|
||||||
expect(result).toBe("/api/ItemTags/filterItemTags/3");
|
expect(result).toBe("/api/ItemTags/filterItemTags/3");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('tagIsEqual()', () => {
|
|
||||||
it('should return true if two tags are equals independent of control attributes', () => {
|
|
||||||
let tag1 = {id: 1, typeFk: 1, value: '1111', showAddIcon: true};
|
|
||||||
let tag2 = {id: 1, typeFk: 1, value: '1111', showAddIcon: false};
|
|
||||||
let equals = controller.tagIsEqual(tag2, tag1);
|
|
||||||
|
|
||||||
expect(equals).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false if two tags aint equal independent of control attributes', () => {
|
|
||||||
let tag1 = {id: 1, typeFk: 1, value: '1111', showAddIcon: true};
|
|
||||||
let tag2 = {id: 1, typeFk: 1, value: '2222', showAddIcon: true};
|
|
||||||
let equals = controller.tagIsEqual(tag2, tag1);
|
|
||||||
|
|
||||||
expect(equals).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('get itemTags', () => {
|
|
||||||
it('should perform a GET query to receive the item tags', () => {
|
|
||||||
controller.$.form = {$setPristine: () => {}};
|
|
||||||
spyOn(controller.$.form, '$setPristine');
|
|
||||||
|
|
||||||
let res = [{id: 1, typeFk: 1, value: '1111'}];
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond(res);
|
|
||||||
$httpBackend.expectGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`);
|
|
||||||
controller.getTags();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$.form.$setPristine).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('submit()', () => {
|
|
||||||
// TODO: Server validation should be implemented
|
|
||||||
xit("should return an error message 'The tag must be unique' when the tag value isnt unique", () => {
|
|
||||||
controller.$.form = [];
|
|
||||||
spyOn(controller.vnApp, 'showError').and.callThrough();
|
|
||||||
controller.tags = [
|
|
||||||
{typeFk: 1, value: 123454, itemFk: 1, id: 1},
|
|
||||||
{typeFk: 1, value: 123454, itemFk: 1}
|
|
||||||
];
|
|
||||||
controller.orgTags = {1: {typeFk: 1, id: 1, value: 123454, itemFk: 1}};
|
|
||||||
controller.submit();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith('The tag must be unique');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should perfom a query to delete tags", () => {
|
|
||||||
controller.orgTags = {1: {id: 1, typeFk: 1, value: '1111'}};
|
|
||||||
controller.tags = [];
|
|
||||||
controller.removedTags = [1];
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
|
|
||||||
$httpBackend.expectPOST(`/item/api/ItemTags/crud`).respond('ok!');
|
|
||||||
controller.submit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should perfom a query to update tags", () => {
|
|
||||||
controller.tags = [{id: 1, typeFk: 1, value: '2222'}];
|
|
||||||
controller.orgTags = {1: {id: 1, typeFk: 1, value: '1111'}};
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
|
|
||||||
$httpBackend.expectPOST(`/item/api/ItemTags/crud`).respond('ok!');
|
|
||||||
controller.submit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should perfom a query to create new tag", () => {
|
|
||||||
controller.tags = [{typeFk: 1, value: 1111, itemFk: 1}];
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
|
|
||||||
$httpBackend.expectPOST(`/item/api/ItemTags/crud`).respond('ok!');
|
|
||||||
controller.submit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should throw 'No changes to save' error when there are no changes to apply", () => {
|
|
||||||
controller.$.watcher = {
|
|
||||||
check: () => {
|
|
||||||
throw new Error('No changes to save');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
controller.orgTags = [];
|
|
||||||
controller.tags = [];
|
|
||||||
|
|
||||||
expect(function() {
|
|
||||||
controller.submit();
|
|
||||||
}).toThrowError();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -33,7 +33,7 @@ export default class Controller {
|
||||||
for (let tax of this.taxes)
|
for (let tax of this.taxes)
|
||||||
data.push({id: tax.id, taxClassFk: tax.taxClassFk});
|
data.push({id: tax.id, taxClassFk: tax.taxClassFk});
|
||||||
|
|
||||||
let url = `/item/api/Items/${this.$stateParams.id}/updateTaxes`;
|
let url = `/item/api/Items/updateTaxes`;
|
||||||
this.$http.post(url, data).then(
|
this.$http.post(url, data).then(
|
||||||
() => this.vnApp.showSuccess(this._.instant('Data saved!'))
|
() => this.vnApp.showSuccess(this._.instant('Data saved!'))
|
||||||
);
|
);
|
||||||
|
|
|
@ -58,8 +58,8 @@ describe('Item', () => {
|
||||||
controller.$onInit();
|
controller.$onInit();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
$httpBackend.when('POST', `/item/api/Items/1/updateTaxes`).respond('ok');
|
$httpBackend.when('POST', `/item/api/Items/updateTaxes`).respond('ok');
|
||||||
$httpBackend.expect('POST', `/item/api/Items/1/updateTaxes`);
|
$httpBackend.expect('POST', `/item/api/Items/updateTaxes`);
|
||||||
controller.submit();
|
controller.submit();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<vn-popover vn-id="popover">
|
||||||
|
<vn-ticket-descriptor
|
||||||
|
ticket="$ctrl.ticket"
|
||||||
|
quicklinks="$ctrl.quicklinks">
|
||||||
|
</vn-ticket-descriptor>
|
||||||
|
</vn-popover>
|
|
@ -0,0 +1,79 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
import Component from 'core/src/lib/component';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
class Controller extends Component {
|
||||||
|
constructor($element, $scope, $http) {
|
||||||
|
super($element, $scope);
|
||||||
|
this.$http = $http;
|
||||||
|
this._quicklinks = {};
|
||||||
|
this.isTooltip = true;
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
set ticketFk(value) {
|
||||||
|
if (value) {
|
||||||
|
let filter = {
|
||||||
|
include: [
|
||||||
|
{relation: 'warehouse', scope: {fields: ['name']}},
|
||||||
|
{relation: 'agencyMode', scope: {fields: ['name']}},
|
||||||
|
{
|
||||||
|
relation: 'client',
|
||||||
|
scope: {
|
||||||
|
fields: ['salesPersonFk', 'name', 'isActive', 'isFreezed', 'isTaxDataChecked'],
|
||||||
|
include: {
|
||||||
|
relation: 'salesPerson',
|
||||||
|
fields: ['firstName', 'name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'tracking',
|
||||||
|
scope: {
|
||||||
|
fields: ['stateFk'],
|
||||||
|
include: {
|
||||||
|
relation: 'state',
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
let json = encodeURIComponent(JSON.stringify(filter));
|
||||||
|
let query = `/ticket/api/Tickets/${value}?filter=${json}`;
|
||||||
|
this.$http.get(query).then(res => {
|
||||||
|
if (res.data)
|
||||||
|
this.ticket = res.data;
|
||||||
|
});
|
||||||
|
} else
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
get quicklinks() {
|
||||||
|
return this._quicklinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
set quicklinks(value = {}) {
|
||||||
|
this._quicklinks = Object.assign(value, this._quicklinks);
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.ticket = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
show() {
|
||||||
|
this.$.popover.parent = this.parent;
|
||||||
|
this.$.popover.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Controller.$inject = ['$element', '$scope', '$http'];
|
||||||
|
|
||||||
|
ngModule.component('vnTicketDescriptorPopover', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
bindings: {
|
||||||
|
ticketFk: '<',
|
||||||
|
quicklinks: '<'
|
||||||
|
},
|
||||||
|
controller: Controller
|
||||||
|
});
|
|
@ -0,0 +1,64 @@
|
||||||
|
import './index.js';
|
||||||
|
|
||||||
|
describe('Item', () => {
|
||||||
|
describe('Component vnTicketDescriptorPopover', () => {
|
||||||
|
let $componentController;
|
||||||
|
let $scope;
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
let $element;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
angular.mock.module('item');
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
||||||
|
$componentController = _$componentController_;
|
||||||
|
$element = angular.element('<vn-ticket-descriptor-popover></vn-ticket-descriptor-popover>');
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
|
$scope = $rootScope.$new();
|
||||||
|
controller = $componentController('vnTicketDescriptorPopover', {$scope, $element, $httpBackend});
|
||||||
|
controller.parent = 'mariano';
|
||||||
|
controller.$.popover = {show: () => {}};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('ticketFk setter', () => {
|
||||||
|
it(`shoud call clear if the given values is null`, () => {
|
||||||
|
spyOn(controller, 'clear');
|
||||||
|
controller.ticketFk = null;
|
||||||
|
|
||||||
|
expect(controller.clear).toHaveBeenCalledWith();
|
||||||
|
expect(controller.ticket).toEqual(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('quicklinks setter', () => {
|
||||||
|
it(`shoud set _quicklinks to a given value`, () => {
|
||||||
|
controller.quicklinks = 3;
|
||||||
|
|
||||||
|
expect(controller._quicklinks).toEqual(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('clear()', () => {
|
||||||
|
it(`should set ticket to null`, () => {
|
||||||
|
controller.ticket = '1';
|
||||||
|
|
||||||
|
controller.clear();
|
||||||
|
|
||||||
|
expect(controller.ticket).toEqual(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('show()', () => {
|
||||||
|
it(`should set $.popover.parent and call $.popover.show`, () => {
|
||||||
|
spyOn(controller.$.popover, 'show');
|
||||||
|
controller.show();
|
||||||
|
|
||||||
|
expect(controller.$.popover.show).toHaveBeenCalledWith();
|
||||||
|
expect(controller.$.popover.parent).toEqual('mariano');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,15 @@
|
||||||
|
vn-ticket-descriptor-popover {
|
||||||
|
vn-ticket-descriptor {
|
||||||
|
display: block;
|
||||||
|
width: 16em;
|
||||||
|
max-height: 28em;
|
||||||
|
|
||||||
|
&>vn-card {
|
||||||
|
margin: 0!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header > a:first-child {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,30 +11,30 @@
|
||||||
<div pad-medium>
|
<div pad-medium>
|
||||||
<h5>{{::$ctrl.client.name}}</h5>
|
<h5>{{::$ctrl.client.name}}</h5>
|
||||||
<vn-label-value label="Id"
|
<vn-label-value label="Id"
|
||||||
value="{{::$ctrl.ticket.id}}">
|
value="{{$ctrl.ticket.id}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value label="Client"
|
<vn-label-value label="Client"
|
||||||
class="link"
|
class="link"
|
||||||
ng-click="$ctrl.showDescriptor($event, $ctrl.ticket.client.id)"
|
ng-click="$ctrl.showDescriptor($event, $ctrl.ticket.client.id)"
|
||||||
value="{{::$ctrl.ticket.client.name}}">
|
value="{{$ctrl.ticket.client.name}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value label="State"
|
<vn-label-value label="State"
|
||||||
value="{{$ctrl.ticket.tracking.state.name}}">
|
value="{{$ctrl.ticket.tracking.state.name}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value label="Sales person"
|
<vn-label-value label="Sales person"
|
||||||
value="{{::$ctrl.ticket.client.salesPerson.firstName}} {{::$ctrl.ticket.client.salesPerson.name}}">
|
value="{{$ctrl.ticket.client.salesPerson.firstName}} {{$ctrl.ticket.client.salesPerson.name}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value label="Shipped"
|
<vn-label-value label="Shipped"
|
||||||
value="{{$ctrl.ticket.shipped | date: 'dd/MM/yyyy HH:mm' }}">
|
value="{{$ctrl.ticket.shipped | date: 'dd/MM/yyyy HH:mm' }}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value label="Agency"
|
<vn-label-value label="Agency"
|
||||||
value="{{::$ctrl.ticket.agencyMode.name}}">
|
value="{{$ctrl.ticket.agencyMode.name}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value label="Warehouse"
|
<vn-label-value label="Warehouse"
|
||||||
value="{{::$ctrl.ticket.warehouse.name}}">
|
value="{{$ctrl.ticket.warehouse.name}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value label="Alias"
|
<vn-label-value label="Alias"
|
||||||
value="{{::$ctrl.ticket.nickname}}">
|
value="{{$ctrl.ticket.nickname}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
</div>
|
</div>
|
||||||
<vn-horizontal pad-medium-bottom class="footer">
|
<vn-horizontal pad-medium-bottom class="footer">
|
|
@ -0,0 +1,30 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
|
||||||
|
class Controller {
|
||||||
|
constructor($http, $scope) {
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.$http = $http;
|
||||||
|
}
|
||||||
|
|
||||||
|
showDescriptor(event, clientFk) {
|
||||||
|
this.$scope.descriptor.clientFk = clientFk;
|
||||||
|
this.$scope.descriptor.parent = event.target;
|
||||||
|
this.$scope.descriptor.show();
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
onDescriptorLoad() {
|
||||||
|
this.$scope.popover.relocate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.$inject = ['$http', '$scope'];
|
||||||
|
|
||||||
|
ngModule.component('vnTicketDescriptor', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
bindings: {
|
||||||
|
ticket: '<'
|
||||||
|
},
|
||||||
|
controller: Controller
|
||||||
|
});
|
|
@ -1 +0,0 @@
|
||||||
export * from './src/locator';
|
|
|
@ -1,14 +0,0 @@
|
||||||
/* {
|
|
||||||
"module": "locator",
|
|
||||||
"name": "Locator",
|
|
||||||
"icon": "add_location",
|
|
||||||
"validations" : false,
|
|
||||||
"routes": [
|
|
||||||
{
|
|
||||||
"url": "/locator",
|
|
||||||
"state": "locator",
|
|
||||||
"component": "vn-locator-index",
|
|
||||||
"acl": ["developer"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
} */
|
|
|
@ -1,39 +0,0 @@
|
||||||
<vn-card margin-large>
|
|
||||||
<vn-vertical pad-medium>
|
|
||||||
<vn-horizontal vn-one margin-large-bottom class="locator-header">
|
|
||||||
<vn-title vn-one>Routes locator</vn-title>
|
|
||||||
<form vn-two vn-horizontal class="filterPanel" ng-submit="$ctrl.searchRoutes()">
|
|
||||||
<vn-textfield vn-one label="Filter" model="$ctrl.search"></vn-textfield>
|
|
||||||
<vn-icon
|
|
||||||
vn-none
|
|
||||||
margin-medium-right
|
|
||||||
pad-medium-top
|
|
||||||
icon="keyboard_arrow_down"
|
|
||||||
ng-click="$ctrl.moreFilters($event)">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-button vn-none pad-small-top label="Filtrar" ng-click="$ctrl.searchRoutes()"></vn-button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<vn-one vn-horizontal>
|
|
||||||
<vn-one></vn-one>
|
|
||||||
<vn-autocomplete vn-two
|
|
||||||
initial-value="$ctrl.filter.warehouseFk"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
field="$ctrl.filter.warehouseFk"
|
|
||||||
url="/production/api/Warehouses"
|
|
||||||
on-change = "$ctrl.onChangeWareHouse(item)"
|
|
||||||
label="Store">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-icon-button vn-none pad-ten-top margin-medium-left icon="refresh" ng-click="$ctrl.refreshRoutes()"></vn-icon-button>
|
|
||||||
</vn-one>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal vn-one margin-large-bottom>
|
|
||||||
<vn-one>
|
|
||||||
<vn-locator-actions routes="$ctrl.routes" states="$ctrl.states" hour-items="$ctrl.hourItems"></vn-locator-actions>
|
|
||||||
</vn-one>
|
|
||||||
<vn-two></vn-two>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-locator-table check-all="$ctrl.checkAll" routes="$ctrl.routes" footer="$ctrl.footer"></vn-locator-table>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
|
@ -1,33 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
|
|
||||||
class LocatorIndex {
|
|
||||||
constructor($state) {
|
|
||||||
this.$state = $state;
|
|
||||||
this.routes = [];
|
|
||||||
|
|
||||||
for (let i = 1; i < 100; i++) {
|
|
||||||
let route = {
|
|
||||||
id: i,
|
|
||||||
zoneFk: Math.floor(Math.random() * 6) + 1,
|
|
||||||
postalcode: 46006,
|
|
||||||
order: Math.floor(Math.random() * 3) + 1,
|
|
||||||
preparado: '25/08',
|
|
||||||
entrada: '26/08',
|
|
||||||
ticket: 1547890 + i,
|
|
||||||
routeFk: Math.floor(Math.random() * 9999) + 1000,
|
|
||||||
alias: `Flores X${Math.floor(Math.random() * 3) + 1}`,
|
|
||||||
bultos: Math.floor(Math.random() * 20) + 10,
|
|
||||||
m3: (Math.random()).toFixed(2),
|
|
||||||
error: (Math.floor(Math.random() * 3) + 1) === 1
|
|
||||||
};
|
|
||||||
route.success = (!route.error && (Math.floor(Math.random() * 3) + 1) === 1);
|
|
||||||
this.routes.push(route);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LocatorIndex.$inject = ['$state'];
|
|
||||||
|
|
||||||
ngModule.component('vnLocatorIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: LocatorIndex
|
|
||||||
});
|
|
|
@ -1,4 +0,0 @@
|
||||||
Routes locator: Routes locator
|
|
||||||
Filter: Filter
|
|
||||||
Store: Store
|
|
||||||
Address: Address
|
|
|
@ -1,4 +0,0 @@
|
||||||
Routes locator: Localizador de rutas
|
|
||||||
Filter: Filtro
|
|
||||||
Store: Almacén
|
|
||||||
Address: Dirección
|
|
|
@ -1,14 +0,0 @@
|
||||||
<vn-horizontal class="actionPanel">
|
|
||||||
<vn-none margin-medium-right>
|
|
||||||
<vn-icon-button icon="local_shipping"></vn-icon-button>
|
|
||||||
</vn-none>
|
|
||||||
<vn-none margin-medium-right>
|
|
||||||
<vn-icon-menu icon="local_shipping" selected="$ctrl.actionRoute" items="[{id:1,name:'test_01'},{id:2,name:'test_02'}]"></vn-icon-menu>
|
|
||||||
</vn-none>
|
|
||||||
<vn-none margin-medium-right>
|
|
||||||
|
|
||||||
</vn-none>
|
|
||||||
<vn-none margin-medium-right>
|
|
||||||
|
|
||||||
</vn-none>
|
|
||||||
</vn-horizontal>
|
|
|
@ -1,13 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
|
|
||||||
class LocatorActions {
|
|
||||||
constructor($state) {
|
|
||||||
this.$state = $state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LocatorActions.$inject = ['$state'];
|
|
||||||
|
|
||||||
ngModule.component('vnLocatorActions', {
|
|
||||||
template: require('./locator-actions.html'),
|
|
||||||
controller: LocatorActions
|
|
||||||
});
|
|
|
@ -1,55 +0,0 @@
|
||||||
<vn-vertical>
|
|
||||||
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
|
|
||||||
<vn-column-header vn-one pad-medium-h>
|
|
||||||
<vn-multi-check
|
|
||||||
check-all="$ctrl.checkAll"
|
|
||||||
models="$ctrl.routes"
|
|
||||||
options="[{id:'all',name:'Todos'},{id:'any',name:'Ninguno'}, {id:'error', name:'Con problema'}, {id:'no-error', name:'Sin problema'}]">
|
|
||||||
</vn-multi-check>
|
|
||||||
</vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="zoneFk" text="Zona"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="postalcode" text="Postal Code"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="order" text="Order" default-order="DESC"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="preparado" text="Preparado"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="entrada" text="Entrada"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="ticket" text="Ticket"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="routeFk" text="ID de ruta"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="alias" text="Alias"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="bultos" text="Bultos"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="m3" text="m3"></vn-column-header>
|
|
||||||
</vn-grid-header>
|
|
||||||
<vn-one class="list list-content">
|
|
||||||
<vn-vertical
|
|
||||||
class="list list-element text-center"
|
|
||||||
ng-repeat="route in $ctrl.pageTable.model track by route.id"
|
|
||||||
ng-class="{warning: route.error, success: route.success}">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-one pad-medium-h></vn-one>
|
|
||||||
<vn-two pad-medium-h>{{::route.zoneFk}}</vn-two>
|
|
||||||
<vn-two pad-medium-h>{{::route.postalcode}}</vn-two>
|
|
||||||
<vn-two pad-medium-h>{{::route.order}}</vn-two>
|
|
||||||
<vn-two pad-medium-h>{{::route.preparado}}</vn-two>
|
|
||||||
<vn-two pad-medium-h>{{::route.entrada}}</vn-two>
|
|
||||||
<vn-two pad-medium-h>{{::route.ticket}}</vn-two>
|
|
||||||
<vn-two pad-medium-h>{{::route.routeFk}}</vn-two>
|
|
||||||
<vn-two pad-medium-h>{{::route.alias}}</vn-two>
|
|
||||||
<vn-two pad-medium-h>{{::route.bultos}}</vn-two>
|
|
||||||
<vn-two pad-medium-h>{{::route.m3}}</vn-two>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal margin-small-top>
|
|
||||||
<vn-none pad-medium-h margin--small-top>
|
|
||||||
<vn-check model="route.checked"></vn-check>
|
|
||||||
</vn-none>
|
|
||||||
<vn-none pad-medium-h></vn-none>
|
|
||||||
<vn-one text-left pad-small border-solid>
|
|
||||||
<strong translate>Address</strong>: {{::route.address}}
|
|
||||||
</vn-one>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-one>
|
|
||||||
<vn-horizontal vn-one class="list list-footer">
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-one>
|
|
||||||
<vn-paging page-change="$ctrl.paginate()" index="$ctrl.pageTable" total="$ctrl.totalFilter"></vn-paging>
|
|
||||||
</vn-one>
|
|
||||||
</vn-vertical>
|
|
|
@ -1,46 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
|
|
||||||
class LocatorTable {
|
|
||||||
constructor($filter) {
|
|
||||||
this.$filter = $filter;
|
|
||||||
this.itemsDisplayedInList = 7;
|
|
||||||
this.pageTable = {
|
|
||||||
filter: {
|
|
||||||
page: 1,
|
|
||||||
size: this.itemsDisplayedInList
|
|
||||||
},
|
|
||||||
model: []
|
|
||||||
};
|
|
||||||
this._routes = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
set routes(value) {
|
|
||||||
this._routes = value;
|
|
||||||
this.totalFilter = this._routes.length;
|
|
||||||
this.pageTable.filter.page = 1;
|
|
||||||
this.paginate();
|
|
||||||
}
|
|
||||||
get routes() {
|
|
||||||
return this._routes;
|
|
||||||
}
|
|
||||||
|
|
||||||
onOrder(field, order) {
|
|
||||||
let reverse = order === 'DESC';
|
|
||||||
this.routes = this.$filter('orderBy')(this.routes, field, reverse);
|
|
||||||
this.paginate();
|
|
||||||
}
|
|
||||||
paginate() {
|
|
||||||
let init = (this.pageTable.filter.page - 1) * this.itemsDisplayedInList;
|
|
||||||
let fin = this.pageTable.filter.page * this.itemsDisplayedInList;
|
|
||||||
this.pageTable.model = this.routes.slice(init, fin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LocatorTable.$inject = ['$filter'];
|
|
||||||
|
|
||||||
ngModule.component('vnLocatorTable', {
|
|
||||||
template: require('./locator-table.html'),
|
|
||||||
bindings: {
|
|
||||||
routes: '<'
|
|
||||||
},
|
|
||||||
controller: LocatorTable
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
export * from './module';
|
|
||||||
|
|
||||||
import './index/index';
|
|
||||||
import './locator-actions/locator-actions';
|
|
||||||
import './locator-table/locator-table';
|
|
|
@ -1,5 +0,0 @@
|
||||||
import {ng} from 'vendor';
|
|
||||||
import 'core';
|
|
||||||
|
|
||||||
const ngModule = ng.module('locator', []);
|
|
||||||
export default ngModule;
|
|
|
@ -1,11 +1,8 @@
|
||||||
auth: []
|
auth: []
|
||||||
client: []
|
client: []
|
||||||
core: []
|
core: []
|
||||||
item: []
|
item: [client]
|
||||||
#locator: []
|
|
||||||
#production: []
|
|
||||||
salix: []
|
salix: []
|
||||||
#route: []
|
|
||||||
ticket: [item, client]
|
ticket: [item, client]
|
||||||
order: [item, ticket]
|
order: [item, ticket]
|
||||||
claim: [item, client]
|
claim: [item, client]
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './src/production';
|
|
|
@ -1,14 +0,0 @@
|
||||||
/* {
|
|
||||||
"module": "production",
|
|
||||||
"name": "Production",
|
|
||||||
"icon": "local_florist",
|
|
||||||
"validations" : false,
|
|
||||||
"routes": [
|
|
||||||
{
|
|
||||||
"url": "/production",
|
|
||||||
"state": "production",
|
|
||||||
"component": "vn-production-index",
|
|
||||||
"acl": ["developer"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
} */
|
|
|
@ -1,39 +0,0 @@
|
||||||
<mg-ajax path="/production/api/States/list" options="vnIndex as states" actions="$ctrl.sharedData.states = states.model;"></mg-ajax>
|
|
||||||
<mg-ajax path="/production/api/FakeProductions/list" options="vnIndexNonAuto as index"></mg-ajax>
|
|
||||||
<vn-card margin-large>
|
|
||||||
<vn-vertical pad-medium>
|
|
||||||
<vn-horizontal vn-one margin-large-bottom class="locator-header">
|
|
||||||
<vn-title vn-one><span translate>Finder</span></vn-title>
|
|
||||||
<vn-searchbar
|
|
||||||
vn-two
|
|
||||||
index="index"
|
|
||||||
on-search="$ctrl.searchTickets(index.filter)"
|
|
||||||
advanced="true"
|
|
||||||
popover="vn-production-filter-panel"
|
|
||||||
ignore-keys = "['page', 'size', 'search', 'warehouseFk']"
|
|
||||||
data ="$ctrl.sharedData">
|
|
||||||
</vn-searchbar>
|
|
||||||
<vn-one vn-horizontal>
|
|
||||||
<vn-one></vn-one>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-two
|
|
||||||
initial-value="$ctrl.filter.warehouseFk"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
field="$ctrl.filter.warehouseFk"
|
|
||||||
url="/production/api/Warehouses"
|
|
||||||
on-change = "$ctrl.onChangeWareHouse(item)"
|
|
||||||
label="Store">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-icon-button vn-none pad-ten-top margin-medium-left icon="refresh" ng-click="$ctrl.refreshTickets()"></vn-icon-button>
|
|
||||||
</vn-one>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal vn-one margin-large-bottom>
|
|
||||||
<vn-one>
|
|
||||||
<vn-production-actions></vn-production-actions>
|
|
||||||
</vn-one>
|
|
||||||
<vn-two></vn-two>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-production-table check-all="$ctrl.checkAll" tickets="$ctrl.tickets" footer="$ctrl.footer"></vn-production-table>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
|
@ -1,103 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
export default class ProductionIndex {
|
|
||||||
constructor($element, $scope, $http, aclConstant) {
|
|
||||||
this.$element = $element;
|
|
||||||
this.$ = $scope;
|
|
||||||
this.$http = $http;
|
|
||||||
this.filter = {};
|
|
||||||
this.tickets = [];
|
|
||||||
|
|
||||||
this.checkAll = 0;
|
|
||||||
this.footer = {
|
|
||||||
total: null,
|
|
||||||
lines: null,
|
|
||||||
meters: null
|
|
||||||
};
|
|
||||||
this._search = null;
|
|
||||||
|
|
||||||
this.sharedData = {
|
|
||||||
states: [],
|
|
||||||
hourItems: []
|
|
||||||
};
|
|
||||||
|
|
||||||
this.child = undefined;
|
|
||||||
this.userProfile = aclConstant.userProfile;
|
|
||||||
this.filter.warehouseFk = this.userProfile.warehouseId;
|
|
||||||
}
|
|
||||||
|
|
||||||
get checkAll() {
|
|
||||||
return this._checkAll;
|
|
||||||
}
|
|
||||||
set checkAll(value) {
|
|
||||||
this._checkAll = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actions Callbacks
|
|
||||||
|
|
||||||
_changeState(ids, stateId, stateName, index) {
|
|
||||||
this.$http.put(`/production/api/TicketStates/${stateId}/changeState`, {tickets: ids}).then(() => {
|
|
||||||
index.forEach(val => {
|
|
||||||
this.tickets[val].state = stateName;
|
|
||||||
this.tickets[val].stateFk = stateId;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_sendMessage(tickets) {
|
|
||||||
this.$http.post(`/production/api/FakeProductions/messageSend`, {tickets: tickets}).then(() => {
|
|
||||||
this.vnApp.showMessage(this.$translate.instant('Success: message send!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_changeTime(ids, time, index) {
|
|
||||||
this.$http.put(`/production/api/Tickets/${time}/changeTime`, {tickets: ids}).then(() => {
|
|
||||||
index.forEach(val => {
|
|
||||||
this.tickets[val].hour = time;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
searchTickets(filter) {
|
|
||||||
this.$.index.filter.filter = Object.assign({}, this.filter, filter || {});
|
|
||||||
this.checkAll = 0;
|
|
||||||
this.$.index.accept().then(json => {
|
|
||||||
this.tickets = json.tickets;
|
|
||||||
this.footer.lines = json.lines;
|
|
||||||
this.footer.meters = json.m3;
|
|
||||||
this.footer.total = json.total;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshTickets() {
|
|
||||||
this.filter = {};
|
|
||||||
this.filter.warehouseFk = this.$.displayValue = this.userProfile.warehouseId;
|
|
||||||
}
|
|
||||||
|
|
||||||
onChangeWareHouse(warehouse) {
|
|
||||||
if (warehouse && warehouse != this.filter.warehouseFk) {
|
|
||||||
this.filter.warehouseFk = warehouse;
|
|
||||||
this.searchTickets(this.filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$onInit() {
|
|
||||||
for (let i = 1; i <= 24; i++) {
|
|
||||||
let hour = [i].join('');
|
|
||||||
if (hour.length === 1) {
|
|
||||||
hour = [0, i].join('');
|
|
||||||
}
|
|
||||||
hour += ':00';
|
|
||||||
this.sharedData.hourItems.push({id: i, name: hour});
|
|
||||||
}
|
|
||||||
this.filter.warehouseFk = this.$.displayValue = this.userProfile.warehouseId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductionIndex.$inject = ['$element', '$scope', '$http', 'aclConstant'];
|
|
||||||
|
|
||||||
ngModule.component('vnProductionIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: ProductionIndex
|
|
||||||
});
|
|
|
@ -1,39 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Production', () => {
|
|
||||||
describe('Component vnProductionIndex', () => {
|
|
||||||
let $componentController;
|
|
||||||
let $httpBackend;
|
|
||||||
let $scope;
|
|
||||||
let controller;
|
|
||||||
let $element;
|
|
||||||
let aclConstant;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
angular.mock.module('production');
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
|
||||||
$element = angular.element('<div></div>');
|
|
||||||
$componentController = _$componentController_;
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
aclConstant = {userProfile: {warehouseId: 1}};
|
|
||||||
controller = $componentController('vnProductionIndex', {$scope: $scope, $element: $element, aclConstant: aclConstant});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('_changeState()', () => {
|
|
||||||
it('should request to update the ticket state', () => {
|
|
||||||
let ids = [1, 2, 3, 4];
|
|
||||||
let stateId = 1;
|
|
||||||
let stateName = 'state';
|
|
||||||
let index = [];
|
|
||||||
controller.tickets = ['ticketVal'];
|
|
||||||
$httpBackend.whenPUT('/production/api/TicketStates/1/changeState', {tickets: ids}).respond({data: 'ticketVal'});
|
|
||||||
$httpBackend.expectPUT('/production/api/TicketStates/1/changeState', {tickets: ids});
|
|
||||||
controller._changeState(ids, stateId, stateName, index);
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,36 +0,0 @@
|
||||||
vn-production-index {
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
button {
|
|
||||||
height: 20px;
|
|
||||||
padding: 0 6px;
|
|
||||||
}
|
|
||||||
vn-searchbar {
|
|
||||||
vn-icon{
|
|
||||||
padding-top: 20px;
|
|
||||||
}
|
|
||||||
vn-icon-button{
|
|
||||||
padding-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[pad-ten-top] {
|
|
||||||
padding-top: 10px;
|
|
||||||
}
|
|
||||||
.icon-square{
|
|
||||||
height: 36px;
|
|
||||||
}
|
|
||||||
.locator-header{
|
|
||||||
i{
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.moreFilters{
|
|
||||||
position: absolute;
|
|
||||||
z-index: 99;
|
|
||||||
background-color: white;
|
|
||||||
padding: 15px;
|
|
||||||
border: 1px solid #9D9D9D;
|
|
||||||
margin-top: 60px;
|
|
||||||
width: 600px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
Production: Production
|
|
|
@ -1,27 +0,0 @@
|
||||||
Finder: Localizador
|
|
||||||
Production: Producción
|
|
||||||
'Error: No tickets selected!': 'Error: ¡No hay tickets seleccionados!'
|
|
||||||
'Error: Action not implemented!': 'Error: ¡Acción no implementada!'
|
|
||||||
State: Estado
|
|
||||||
Alarm: Alarma
|
|
||||||
Agencies: Agencias
|
|
||||||
Agency: Agencia
|
|
||||||
Store: Almacén
|
|
||||||
Printed: Impreso
|
|
||||||
Commercial: Comercial
|
|
||||||
Hour: Hora
|
|
||||||
Lines: Líneas
|
|
||||||
Boxes: Cajas
|
|
||||||
Comment: Comentario
|
|
||||||
Message: Mensaje
|
|
||||||
Send: Enviar
|
|
||||||
Date: Fecha
|
|
||||||
Ticket ID: ID Ticket
|
|
||||||
Route ID: ID Ruta
|
|
||||||
Province: Provincia
|
|
||||||
Filter: Filtrar
|
|
||||||
Cancel: Cancelar
|
|
||||||
Worker: Trabajador
|
|
||||||
Town: Población
|
|
||||||
Client ID: ID Cliente
|
|
||||||
Ticket with incidence: Ticket con incidencia
|
|
|
@ -1,5 +0,0 @@
|
||||||
import {ng} from 'vendor';
|
|
||||||
import 'core';
|
|
||||||
|
|
||||||
const ngModule = ng.module('production', []);
|
|
||||||
export default ngModule;
|
|
|
@ -1,15 +0,0 @@
|
||||||
<vn-horizontal class="actionPanel">
|
|
||||||
<vn-button vn-none margin-medium-right label="Printed" ng-click="$ctrl.doAction('markPrinted')"></vn-button>
|
|
||||||
<vn-none margin-medium-right>
|
|
||||||
<vn-icon-menu icon="assignment" items="$ctrl.parent.sharedData.states" selected="$ctrl.actionState"></vn-icon-menu>
|
|
||||||
</vn-none>
|
|
||||||
<vn-none margin-medium-right>
|
|
||||||
<vn-icon-button icon="textsms" ng-click="$ctrl.doAction('addComment')"></vn-icon-button>
|
|
||||||
</vn-none>
|
|
||||||
<vn-none margin-medium-right>
|
|
||||||
<vn-icon-menu icon="person" url="/client/api/Clients/listWorkers" selected="$ctrl.actionWorker"></vn-icon-menu>
|
|
||||||
</vn-none>
|
|
||||||
<vn-none margin-medium-right>
|
|
||||||
<vn-icon-menu icon="query_builder" items="$ctrl.parent.sharedData.hourItems" selected="$ctrl.actionHours"></vn-icon-menu>
|
|
||||||
</vn-none>
|
|
||||||
</vn-horizontal>
|
|
|
@ -1,118 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
|
|
||||||
export default class ProductionActions {
|
|
||||||
constructor($http, $translate, vnApp) {
|
|
||||||
this.$http = $http;
|
|
||||||
this.$translate = $translate;
|
|
||||||
this.vnApp = vnApp;
|
|
||||||
|
|
||||||
this._actionState = null;
|
|
||||||
this._actionWorker = null;
|
|
||||||
this._actionHours = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
set actionState(value) {
|
|
||||||
this._actionState = value;
|
|
||||||
this.doAction('changeState');
|
|
||||||
}
|
|
||||||
get actionState() {
|
|
||||||
return this._actionState;
|
|
||||||
}
|
|
||||||
|
|
||||||
set actionHours(value) {
|
|
||||||
this._actionHours = value;
|
|
||||||
this.doAction('changeTime');
|
|
||||||
}
|
|
||||||
get actionHours() {
|
|
||||||
return this._actionHours;
|
|
||||||
}
|
|
||||||
|
|
||||||
set actionWorker(value) {
|
|
||||||
this._actionWorker = value;
|
|
||||||
this.doAction('changeWorker');
|
|
||||||
}
|
|
||||||
get actionWorker() {
|
|
||||||
return this._actionWorker;
|
|
||||||
}
|
|
||||||
|
|
||||||
_changeState(ids, sateteId) {
|
|
||||||
this.$http.put(`/production/api/TicketStates/${sateteId}/changeState`, {tickets: ids})
|
|
||||||
.then(
|
|
||||||
() => {
|
|
||||||
this.parent.searchTickets();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_sendMessage(tickets) {
|
|
||||||
this.$http.post(`/production/api/FakeProductions/messageSend`, {tickets: tickets})
|
|
||||||
.then(
|
|
||||||
() => {
|
|
||||||
this.vnApp.showMessage(this.$translate.instant('Success: message send!'));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_changeTime(ids, time, index) {
|
|
||||||
this.$http.put(`/production/api/Tickets/${time}/changeTime`, {tickets: ids})
|
|
||||||
.then(
|
|
||||||
() => {
|
|
||||||
this.parent.searchTickets();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_changeWorker(ids, workerFk, index) {
|
|
||||||
this.$http.put(`/production/api/Tickets/${workerFk}/changeWorker`, {tickets: ids})
|
|
||||||
.then(
|
|
||||||
() => {
|
|
||||||
this.parent.searchTickets();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
doAction(actionName) {
|
|
||||||
let ids = [];
|
|
||||||
let index = [];
|
|
||||||
let tickets = [];
|
|
||||||
this.parent.tickets.forEach(
|
|
||||||
(val, i) => {
|
|
||||||
if (val.checked) {
|
|
||||||
ids.push(val.ticketFk);
|
|
||||||
index.push(i);
|
|
||||||
tickets.push({ticketFk: val.ticketFk, salesPerson: val.salesPerson});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (tickets.length) {
|
|
||||||
switch (actionName) {
|
|
||||||
case 'changeState' :
|
|
||||||
this._changeState(ids, this.actionState.id);
|
|
||||||
break;
|
|
||||||
case 'addComment':
|
|
||||||
this._sendMessage(tickets);
|
|
||||||
break;
|
|
||||||
case 'markPrinted':
|
|
||||||
this._changeState(ids, 4);
|
|
||||||
break;
|
|
||||||
case 'changeTime':
|
|
||||||
this._changeTime(ids, this.actionHours.name, index);
|
|
||||||
break;
|
|
||||||
case 'changeWorker':
|
|
||||||
this._changeWorker(ids, this.actionWorker.id, index);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.vnApp.showMessage(this.$translate.instant('Error: Action not implemented!'));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.vnApp.showMessage(this.$translate.instant('Error: No tickets selected!'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductionActions.$inject = ['$http', '$translate', 'vnApp'];
|
|
||||||
|
|
||||||
ngModule.component('vnProductionActions', {
|
|
||||||
template: require('./production-actions.html'),
|
|
||||||
controller: ProductionActions,
|
|
||||||
require: {
|
|
||||||
parent: '^^vnProductionIndex'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,6 +0,0 @@
|
||||||
<form ng-submit="$ctrl.onComment($ctrl.ids, $ctrl.comment)" pad-large>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield vn-one label="Message" model="$ctrl.comment"></vn-textfield>
|
|
||||||
<vn-submit vn-none pad-small-top label="Send"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
|
@ -1,5 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
|
|
||||||
ngModule.component('vnProductionComment', {
|
|
||||||
template: require('./production-comment.html')
|
|
||||||
});
|
|
|
@ -1,32 +0,0 @@
|
||||||
<form ng-submit="$ctrl.onSubmit($ctrl.filter)" pad-large>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield vn-one label="Route ID" model="$ctrl.filter.routeFk"></vn-textfield>
|
|
||||||
<vn-date-picker vn-one label="Date" model="$ctrl.filter.date"></vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
field="$ctrl.filter.provinceFk"
|
|
||||||
url="/client/api/Provinces"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Province">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
data="$ctrl.data.hourItems"
|
|
||||||
label="Hour"
|
|
||||||
value-field="name"
|
|
||||||
field="$ctrl.filter.hour"
|
|
||||||
>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete vn-one margin-medium-right field="$ctrl.filter.stateFk" data="$ctrl.data.states" label="State"></vn-autocomplete>
|
|
||||||
<vn-autocomplete vn-one margin-medium-right field="$ctrl.filter.agencyFk" url="/production/api/Agencies" label="Agency"></vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal margin-large-top>
|
|
||||||
<vn-one></vn-one>
|
|
||||||
<vn-none>
|
|
||||||
<vn-submit label="Filter"></vn-submit>
|
|
||||||
</vn-none>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
|
@ -1,5 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
|
|
||||||
ngModule.component('vnProductionFilterPanel', {
|
|
||||||
template: require('./production-filters.html')
|
|
||||||
});
|
|
|
@ -1,92 +0,0 @@
|
||||||
<vn-vertical>
|
|
||||||
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
|
|
||||||
<vn-none min-none></vn-none>
|
|
||||||
<vn-column-header vn-none min-none>
|
|
||||||
<vn-multi-check
|
|
||||||
check-all="$ctrl.checkAll"
|
|
||||||
models="$ctrl.tickets"
|
|
||||||
options="[{id:'all',name:'Todos'},{id:'any',name:'Ninguno'},{id:'problem',name:'Con incidencia'},{id:'no-problem',name:'Sin incidencia'}]">
|
|
||||||
</vn-multi-check>
|
|
||||||
</vn-column-header>
|
|
||||||
<vn-column-header vn-one pad-medium-h field="ticketFk" text="Ticket ID"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="agency" text="Agency"></vn-column-header>
|
|
||||||
<vn-column-header vn-one pad-medium-h field="routeFk" text="Route ID"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="salesPerson" text="Commercial"></vn-column-header>
|
|
||||||
<vn-column-header vn-two pad-medium-h field="worker" text="Worker"></vn-column-header>
|
|
||||||
<vn-column-header vn-one pad-medium-h field="hour" text="Hour"></vn-column-header>
|
|
||||||
<vn-column-header vn-one pad-medium-h field="state" text="State"></vn-column-header>
|
|
||||||
<vn-column-header vn-one pad-medium-h field="lines" text="Lines"></vn-column-header>
|
|
||||||
<vn-column-header vn-one pad-medium-h field="m3" text="m3"></vn-column-header>
|
|
||||||
<vn-column-header vn-one pad-medium-h field="boxes" text="Boxes"></vn-column-header>
|
|
||||||
<vn-none min-none></vn-none>
|
|
||||||
</vn-grid-header>
|
|
||||||
<vn-one class="list list-content">
|
|
||||||
<vn-horizontal vn-one class="list list-element text-center" ng-repeat="ticket in $ctrl.pageTable.model" ng-class="{warning: ticket.problem==='RIESGO'}">
|
|
||||||
<vn-none>
|
|
||||||
<vn-icon
|
|
||||||
margin-small-left
|
|
||||||
icon="report_problem"
|
|
||||||
ng-if="ticket.problem"
|
|
||||||
vn-tooltip="{{ticket.problem}}">
|
|
||||||
</vn-icon>
|
|
||||||
</vn-none>
|
|
||||||
<vn-none>
|
|
||||||
<vn-check model="ticket.checked"></vn-check>
|
|
||||||
</vn-none>
|
|
||||||
<vn-one pad-medium-h>{{::ticket.ticketFk}}</vn-one>
|
|
||||||
<vn-two pad-medium-h>{{::ticket.agency}}</vn-two>
|
|
||||||
<vn-one pad-medium-h>{{::ticket.routeFk}}</vn-one>
|
|
||||||
<vn-two pad-medium-h>{{::ticket.salesPerson | ucwords}}</vn-two>
|
|
||||||
<vn-two pad-medium-h>{{::ticket.worker | ucwords}}</vn-two>
|
|
||||||
<vn-one pad-medium-h>{{::ticket.hour}}</vn-one>
|
|
||||||
<vn-one pad-medium-h>{{::ticket.state}}</vn-one>
|
|
||||||
<vn-one pad-medium-h>{{::ticket.lines}}</vn-one>
|
|
||||||
<vn-one pad-medium-h>{{::ticket.m3}}</vn-one>
|
|
||||||
<vn-one pad-medium-h>{{::ticket.boxes}}</vn-one>
|
|
||||||
<vn-none>
|
|
||||||
<vn-icon
|
|
||||||
icon="more"
|
|
||||||
vn-tooltip
|
|
||||||
vn-tooltip-id="more-tooltip">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-tooltip position="left" id="more-tooltip">
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-horizontal class="list list-header">
|
|
||||||
<vn-one margin-medium-right translate>Town</vn-one>
|
|
||||||
<vn-one margin-medium-right translate>Province</vn-one>
|
|
||||||
<vn-two margin-medium-right translate>Client ID</vn-two>
|
|
||||||
<vn-two translate>Worker</vn-two>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="list list-element">
|
|
||||||
<vn-one margin-medium-right>{{::ticket.city | ucwords}}</vn-one>
|
|
||||||
<vn-one margin-medium-right>{{::ticket.province | ucwords}}</vn-one>
|
|
||||||
<vn-two margin-medium-right>{{::ticket.client | ucwords}}</vn-two>
|
|
||||||
<vn-two>{{::ticket.worker | ucwords}}</vn-two>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-tooltip>
|
|
||||||
</vn-none>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-one>
|
|
||||||
<vn-horizontal vn-one class="list list-footer">
|
|
||||||
<vn-none></vn-none>
|
|
||||||
<vn-none></vn-none>
|
|
||||||
<vn-one pad-medium-h>
|
|
||||||
<span translate="Resultados"></span>:
|
|
||||||
<span>{{$ctrl.footer.total}}</span>
|
|
||||||
</vn-one>
|
|
||||||
<vn-two pad-medium-h></vn-two>
|
|
||||||
<vn-one pad-medium-h></vn-one>
|
|
||||||
<vn-two pad-medium-h></vn-two>
|
|
||||||
<vn-two pad-medium-h></vn-two>
|
|
||||||
<vn-one pad-medium-h></vn-one>
|
|
||||||
<vn-one pad-medium-h></vn-one>
|
|
||||||
<vn-one pad-medium-h text-center>{{$ctrl.footer.lines}}</vn-one>
|
|
||||||
<vn-one pad-medium-h text-center>{{$ctrl.footer.meters}}</vn-one>
|
|
||||||
<vn-one pad-medium-h></vn-one>
|
|
||||||
<vn-none></vn-none>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-one>
|
|
||||||
<vn-paging page-change="$ctrl.pageTickets()" index="$ctrl.pageTable" total="$ctrl.totalFilter"></vn-paging>
|
|
||||||
</vn-one>
|
|
||||||
</vn-vertical>
|
|
|
@ -1,56 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
|
|
||||||
export class ProductionTable {
|
|
||||||
constructor($filter) {
|
|
||||||
this.$filter = $filter;
|
|
||||||
this._tickets = [];
|
|
||||||
this.itemsDisplayedInList = 14;
|
|
||||||
this._checkAll = 0;
|
|
||||||
this.pageTable = {
|
|
||||||
filter: {
|
|
||||||
page: 1,
|
|
||||||
size: this.itemsDisplayedInList
|
|
||||||
},
|
|
||||||
model: []
|
|
||||||
};
|
|
||||||
this.filteredField = null;
|
|
||||||
this.filteredReverse = null;
|
|
||||||
}
|
|
||||||
get checkAll() {
|
|
||||||
return this._checkAll;
|
|
||||||
}
|
|
||||||
set checkAll(value) {
|
|
||||||
this._checkAll = value;
|
|
||||||
}
|
|
||||||
set tickets(value) {
|
|
||||||
this._tickets = this.filteredField ? this.$filter('orderBy')(value, this.filteredField, this.filteredReverse) : value;
|
|
||||||
this.totalFilter = this._tickets.length;
|
|
||||||
this.pageTable.filter.page = 1;
|
|
||||||
this.pageTickets();
|
|
||||||
}
|
|
||||||
get tickets() {
|
|
||||||
return this._tickets;
|
|
||||||
}
|
|
||||||
onOrder(field, order) {
|
|
||||||
this.filteredField = field;
|
|
||||||
this.filteredReverse = order === 'DESC';
|
|
||||||
this.tickets = this.tickets; // call tickets setter
|
|
||||||
}
|
|
||||||
pageTickets() {
|
|
||||||
let init = (this.pageTable.filter.page - 1) * this.itemsDisplayedInList;
|
|
||||||
let fin = this.pageTable.filter.page * this.itemsDisplayedInList;
|
|
||||||
this.pageTable.model = this.tickets.slice(init, fin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductionTable.$inject = ['$filter'];
|
|
||||||
|
|
||||||
ngModule.component('vnProductionTable', {
|
|
||||||
template: require('./production-table.html'),
|
|
||||||
bindings: {
|
|
||||||
tickets: '<',
|
|
||||||
footer: '<',
|
|
||||||
checkAll: '<'
|
|
||||||
},
|
|
||||||
controller: ProductionTable
|
|
||||||
});
|
|
|
@ -1,7 +0,0 @@
|
||||||
export * from './module';
|
|
||||||
|
|
||||||
// import components
|
|
||||||
import './index/index';
|
|
||||||
import './production-filters/production-filters';
|
|
||||||
import './production-actions/production-actions';
|
|
||||||
import './production-table/production-table';
|
|
|
@ -20,7 +20,6 @@ name: Nombre
|
||||||
phone: Teléfono
|
phone: Teléfono
|
||||||
Preview: Vista previa
|
Preview: Vista previa
|
||||||
Profile: Perfil
|
Profile: Perfil
|
||||||
Production : Producción
|
|
||||||
Push on applications menu: Para abrir un módulo pulsa en el menú de aplicaciones
|
Push on applications menu: Para abrir un módulo pulsa en el menú de aplicaciones
|
||||||
Return to module index: Volver a la página principal del módulo
|
Return to module index: Volver a la página principal del módulo
|
||||||
Routes: Rutas
|
Routes: Rutas
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
export default {
|
export default {
|
||||||
client:
|
client:
|
||||||
cb => require.ensure([], () => cb(require('client'))),
|
cb => require.ensure([], () => cb(require('client'))),
|
||||||
production:
|
|
||||||
cb => require.ensure([], () => cb(require('production'))),
|
|
||||||
route:
|
route:
|
||||||
cb => require.ensure([], () => cb(require('route'))),
|
cb => require.ensure([], () => cb(require('route'))),
|
||||||
locator:
|
|
||||||
cb => require.ensure([], () => cb(require('locator'))),
|
|
||||||
item:
|
item:
|
||||||
cb => require.ensure([], () => cb(require('item'))),
|
cb => require.ensure([], () => cb(require('item'))),
|
||||||
ticket:
|
ticket:
|
||||||
|
|
|
@ -163,7 +163,7 @@
|
||||||
"params": {
|
"params": {
|
||||||
"ticket": "$ctrl.ticket"
|
"ticket": "$ctrl.ticket"
|
||||||
},
|
},
|
||||||
"acl": ["production"]
|
"acl": ["production", "administrative"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url" : "/sale-checked",
|
"url" : "/sale-checked",
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
|
|
||||||
class Controller {
|
|
||||||
|
|
||||||
constructor($http, $scope) {
|
|
||||||
this.$ = $scope;
|
|
||||||
this.$http = $http;
|
|
||||||
}
|
|
||||||
|
|
||||||
getClientDebt(clientFk) {
|
|
||||||
this.$http.get(`/client/api/Clients/${clientFk}/getDebt`).then(response => {
|
|
||||||
this.clientDebt = response.data.debt;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
showDescriptor(event, clientFk) {
|
|
||||||
this.$.descriptor.clientFk = clientFk;
|
|
||||||
this.$.descriptor.parent = event.target;
|
|
||||||
this.$.descriptor.show();
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopImmediatePropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
onDescriptorLoad() {
|
|
||||||
this.$.popover.relocate();
|
|
||||||
}
|
|
||||||
|
|
||||||
$onChanges() {
|
|
||||||
if (this.ticket)
|
|
||||||
this.getClientDebt(this.ticket.clientFk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$http', '$scope'];
|
|
||||||
|
|
||||||
ngModule.component('vnTicketDescriptor', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
bindings: {
|
|
||||||
ticket: '<'
|
|
||||||
},
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,36 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('Ticket', () => {
|
|
||||||
describe('Component vnTicketDescriptor', () => {
|
|
||||||
let $componentController;
|
|
||||||
let controller;
|
|
||||||
let $scope;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
angular.mock.module('ticket');
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
|
||||||
$componentController = _$componentController_;
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
controller = $componentController('vnTicketDescriptor', {$scope: $scope});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('getClientDebt()', () => {
|
|
||||||
it('should store the client debt into the controller', () => {
|
|
||||||
let clientFk = 101;
|
|
||||||
let response = {debt: 10};
|
|
||||||
|
|
||||||
$httpBackend.when('GET', `/client/api/Clients/${clientFk}/getDebt`).respond(response);
|
|
||||||
$httpBackend.expect('GET', `/client/api/Clients/${clientFk}/getDebt`);
|
|
||||||
controller.getClientDebt(clientFk);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.clientDebt).toEqual(response.debt);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -21,7 +21,7 @@
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
<vn-th></vn-th>
|
<vn-th></vn-th>
|
||||||
<vn-th field="ticketFk" number>Id</vn-th>
|
<vn-th field="id" number>Id</vn-th>
|
||||||
<vn-th field="salesPersonFk">Salesperson</vn-th>
|
<vn-th field="salesPersonFk">Salesperson</vn-th>
|
||||||
<vn-th field="shipped">Date</vn-th>
|
<vn-th field="shipped">Date</vn-th>
|
||||||
<vn-th>Hour</vn-th>
|
<vn-th>Hour</vn-th>
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
<vn-tbody>
|
<vn-tbody>
|
||||||
<vn-tr ng-repeat="ticket in tickets"
|
<vn-tr ng-repeat="ticket in tickets"
|
||||||
class="{{::$ctrl.compareDate(ticket.shipped)}} clickable"
|
class="{{::$ctrl.compareDate(ticket.shipped)}} clickable"
|
||||||
ui-sref="ticket.card.summary({id: {{::ticket.ticketFk}}})">
|
ui-sref="ticket.card.summary({id: {{::ticket.id}}})">
|
||||||
<vn-td>
|
<vn-td>
|
||||||
<vn-icon ng-show="ticket.problem" class="bright"
|
<vn-icon ng-show="ticket.problem" class="bright"
|
||||||
vn-tooltip="{{ticket.problem}}"
|
vn-tooltip="{{ticket.problem}}"
|
||||||
|
|
|
@ -2,7 +2,7 @@ import ngModule from '../module';
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller {
|
||||||
constructor($scope) {
|
constructor($scope) {
|
||||||
this.$ = $scope;
|
this.$scope = $scope;
|
||||||
this.ticketSelected = null;
|
this.ticketSelected = null;
|
||||||
|
|
||||||
this.filter = {
|
this.filter = {
|
||||||
|
@ -61,13 +61,13 @@ export default class Controller {
|
||||||
case 'search':
|
case 'search':
|
||||||
return /^\d+$/.test(value)
|
return /^\d+$/.test(value)
|
||||||
? {id: value}
|
? {id: value}
|
||||||
: {nickname: {regexp: value}};
|
: {nickname: {like: value}};
|
||||||
case 'from':
|
case 'from':
|
||||||
return {shipped: {gte: value}};
|
return {shipped: {gte: value}};
|
||||||
case 'to':
|
case 'to':
|
||||||
return {shipped: {lte: value}};
|
return {shipped: {lte: value}};
|
||||||
case 'nickname':
|
case 'nickname':
|
||||||
return {[param]: {regexp: value}};
|
return {[param]: {like: value}};
|
||||||
case 'id':
|
case 'id':
|
||||||
case 'clientFk':
|
case 'clientFk':
|
||||||
case 'agencyModeFk':
|
case 'agencyModeFk':
|
||||||
|
@ -92,21 +92,21 @@ export default class Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
showDescriptor(event, clientFk) {
|
showDescriptor(event, clientFk) {
|
||||||
this.$.descriptor.clientFk = clientFk;
|
this.$scope.descriptor.clientFk = clientFk;
|
||||||
this.$.descriptor.parent = event.target;
|
this.$scope.descriptor.parent = event.target;
|
||||||
this.$.descriptor.show();
|
this.$scope.descriptor.show();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopImmediatePropagation();
|
event.stopImmediatePropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
onDescriptorLoad() {
|
onDescriptorLoad() {
|
||||||
this.$.popover.relocate();
|
this.$scope.popover.relocate();
|
||||||
}
|
}
|
||||||
|
|
||||||
preview(event, ticket) {
|
preview(event, ticket) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopImmediatePropagation();
|
event.stopImmediatePropagation();
|
||||||
this.$.dialogSummaryTicket.show();
|
this.$scope.dialogSummaryTicket.show();
|
||||||
this.ticketSelected = ticket;
|
this.ticketSelected = ticket;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ describe('ticket', () => {
|
||||||
let value = 'Bruce';
|
let value = 'Bruce';
|
||||||
let result = controller.exprBuilder(param, value);
|
let result = controller.exprBuilder(param, value);
|
||||||
|
|
||||||
expect(result).toEqual({nickname: {regexp: 'Bruce'}});
|
expect(result).toEqual({nickname: {like: 'Bruce'}});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a formated object with the date in case of from', () => {
|
it('should return a formated object with the date in case of from', () => {
|
||||||
|
@ -52,7 +52,7 @@ describe('ticket', () => {
|
||||||
let value = 'Bruce';
|
let value = 'Bruce';
|
||||||
let result = controller.exprBuilder(param, value);
|
let result = controller.exprBuilder(param, value);
|
||||||
|
|
||||||
expect(result).toEqual({nickname: {regexp: 'Bruce'}});
|
expect(result).toEqual({nickname: {like: 'Bruce'}});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a formated object with the warehouseFk in case of warehouseFk', () => {
|
it('should return a formated object with the warehouseFk in case of warehouseFk', () => {
|
||||||
|
@ -84,14 +84,14 @@ describe('ticket', () => {
|
||||||
it('should call preventDefault and stopImmediatePropagation from event and show', () => {
|
it('should call preventDefault and stopImmediatePropagation from event and show', () => {
|
||||||
let event = jasmine.createSpyObj('event', ['preventDefault', 'stopImmediatePropagation']);
|
let event = jasmine.createSpyObj('event', ['preventDefault', 'stopImmediatePropagation']);
|
||||||
|
|
||||||
controller.$ = {dialogSummaryTicket: {show: () => {}}};
|
controller.$scope = {dialogSummaryTicket: {show: () => {}}};
|
||||||
spyOn(controller.$.dialogSummaryTicket, 'show');
|
spyOn(controller.$scope.dialogSummaryTicket, 'show');
|
||||||
let ticket = {};
|
let ticket = {};
|
||||||
controller.preview(event, ticket);
|
controller.preview(event, ticket);
|
||||||
|
|
||||||
expect(event.preventDefault).toHaveBeenCalledWith();
|
expect(event.preventDefault).toHaveBeenCalledWith();
|
||||||
expect(event.stopImmediatePropagation).toHaveBeenCalledWith();
|
expect(event.stopImmediatePropagation).toHaveBeenCalledWith();
|
||||||
expect(controller.$.dialogSummaryTicket.show).toHaveBeenCalledWith();
|
expect(controller.$scope.dialogSummaryTicket.show).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -44,7 +44,6 @@ Shipment: Salida
|
||||||
Shipped: F. envio
|
Shipped: F. envio
|
||||||
Some fields are invalid: Algunos campos no son válidos
|
Some fields are invalid: Algunos campos no son válidos
|
||||||
State: Estado
|
State: Estado
|
||||||
The observation type must be unique: El tipo de observación debe ser único
|
|
||||||
Tickets: Tickets
|
Tickets: Tickets
|
||||||
Total import: Importe total
|
Total import: Importe total
|
||||||
Warehouse: Almacén
|
Warehouse: Almacén
|
||||||
|
|
|
@ -1,38 +1,36 @@
|
||||||
|
<vn-crud-model
|
||||||
|
vn-id="model"
|
||||||
|
url="/ticket/api/TicketObservations"
|
||||||
|
fields="['id', 'ticketFk', 'observationTypeFk', 'description']"
|
||||||
|
link="{ticketFk: $ctrl.$stateParams.id}"
|
||||||
|
data="observations">
|
||||||
|
</vn-crud-model>
|
||||||
|
<vn-crud-model
|
||||||
|
url="/ticket/api/ObservationTypes"
|
||||||
|
data="observationTypes">
|
||||||
|
</vn-crud-model>
|
||||||
<vn-watcher
|
<vn-watcher
|
||||||
vn-id="watcher"
|
vn-id="watcher"
|
||||||
url="/ticket/api/Observation"
|
data="observations"
|
||||||
id-field="id"
|
|
||||||
data="$ctrl.address"
|
|
||||||
form="form">
|
form="form">
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
<form name="form" ng-submit="$ctrl.submit()">
|
<form name="form" ng-submit="$ctrl.onSubmit()">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-one margin-medium-top>
|
<vn-one margin-medium-top>
|
||||||
<vn-title>Notes</vn-title>
|
<vn-title>Notes</vn-title>
|
||||||
<mg-ajax path="/ticket/api/ObservationTypes" options="mgIndex as observationTypes"></mg-ajax>
|
<vn-horizontal ng-repeat="observation in observations track by $index">
|
||||||
<vn-horizontal ng-repeat="ticketObservation in $ctrl.ticketObservations track by $index">
|
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
ng-if="!ticketObservation.id"
|
ng-attr-disabled="observation.id ? true : false"
|
||||||
vn-one
|
field="observation.observationTypeFk"
|
||||||
vn-focus
|
data="observationTypes"
|
||||||
initial-data="ticketObservation.observationType"
|
|
||||||
field="ticketObservation.observationTypeFk"
|
|
||||||
data="observationTypes.model"
|
|
||||||
show-field="description"
|
show-field="description"
|
||||||
label="Observation type">
|
label="Observation type" vn-one vn-focus>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-textfield
|
|
||||||
ng-if="ticketObservation.id"
|
|
||||||
vn-one
|
|
||||||
label="Observation type"
|
|
||||||
model="ticketObservation.observationType.description"
|
|
||||||
disabled="true">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-two
|
vn-two
|
||||||
margin-large-right
|
margin-large-right
|
||||||
label="Description"
|
label="Description"
|
||||||
model="ticketObservation.description"
|
model="observation.description"
|
||||||
rule="ticketObservation.description">
|
rule="ticketObservation.description">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-auto pad-medium-top>
|
<vn-auto pad-medium-top>
|
||||||
|
@ -41,7 +39,7 @@
|
||||||
medium-grey
|
medium-grey
|
||||||
vn-tooltip="Remove note"
|
vn-tooltip="Remove note"
|
||||||
icon="remove_circle_outline"
|
icon="remove_circle_outline"
|
||||||
ng-click="$ctrl.removeObservation($index)">
|
ng-click="model.remove($index)">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
</vn-auto>
|
</vn-auto>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
@ -51,8 +49,8 @@
|
||||||
pointer vn-tooltip="Add note"
|
pointer vn-tooltip="Add note"
|
||||||
icon="add_circle"
|
icon="add_circle"
|
||||||
vn-bind="+"
|
vn-bind="+"
|
||||||
ng-if="observationTypes.model.length > $ctrl.ticketObservations.length"
|
ng-if="observationTypes.length > observations.length"
|
||||||
ng-click="$ctrl.addObservation()">
|
ng-click="model.insert()">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
|
|
|
@ -1,136 +1,21 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor($stateParams, $scope, $http, $translate, vnApp) {
|
constructor($stateParams, $scope) {
|
||||||
this.params = $stateParams;
|
this.$stateParams = $stateParams;
|
||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
this.$http = $http;
|
|
||||||
this.$translate = $translate;
|
|
||||||
this.vnApp = vnApp;
|
|
||||||
|
|
||||||
this.ticketObservations = [];
|
|
||||||
this.oldObservations = {};
|
|
||||||
this.removedObservations = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_setIconAdd() {
|
onSubmit() {
|
||||||
if (this.ticketObservations.length) {
|
this.$scope.watcher.check();
|
||||||
this.ticketObservations.map(element => {
|
this.$scope.model.save().then(() => {
|
||||||
element.showAddIcon = false;
|
this.$scope.watcher.notifySaved();
|
||||||
return true;
|
this.$scope.model.refresh();
|
||||||
});
|
|
||||||
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.showError(this.$translate.instant('Some fields are invalid'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (repeatedType) {
|
|
||||||
return this.vnApp.showError(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/crudTicketObservation`, observationsObj).then(() => {
|
|
||||||
this.getObservations();
|
|
||||||
this._unsetDirtyForm();
|
|
||||||
this.$scope.watcher.notifySaved();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.vnApp.showError(this.$translate.instant('No changes to save'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$onInit() {
|
|
||||||
this.getObservations();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp'];
|
Controller.$inject = ['$stateParams', '$scope'];
|
||||||
|
|
||||||
ngModule.component('vnTicketObservation', {
|
ngModule.component('vnTicketObservation', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -1,164 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('ticket', () => {
|
|
||||||
describe('Component vnTicketObservation', () => {
|
|
||||||
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_;
|
|
||||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
|
||||||
controller = $componentController('vnTicketObservation', {$state: $state});
|
|
||||||
controller.$scope.watcher = {
|
|
||||||
notifySaved: () => {}
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
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.ticketObservations.length).toEqual(1);
|
|
||||||
expect(controller.ticketObservations[0].id).toBe(undefined);
|
|
||||||
expect(controller.ticketObservations[0].showAddIcon).toBeTruthy();
|
|
||||||
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
|
|
||||||
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.ticketObservations.length).toEqual(2);
|
|
||||||
expect(controller.ticketObservations[0].showAddIcon).toBeFalsy();
|
|
||||||
expect(controller.ticketObservations[1].showAddIcon).toBeTruthy();
|
|
||||||
expect(controller.ticketObservations[index]).toBe(undefined);
|
|
||||||
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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 response = [{id: 1, observationTypeFk: 1, description: 'one'}];
|
|
||||||
spyOn(controller, 'setOldObservations');
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`).respond(response);
|
|
||||||
$httpBackend.expectGET(`/ticket/api/TicketObservations?filter={"where":{},"include":["observationType"]}`);
|
|
||||||
controller.getObservations();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.setOldObservations).toHaveBeenCalledWith(jasmine.any(Object));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('submit()', () => {
|
|
||||||
it("should return an error message 'Some fields are invalid'", () => {
|
|
||||||
controller.$scope.form = {};
|
|
||||||
controller.$scope.form.$invalid = true;
|
|
||||||
spyOn(controller.vnApp, 'showError').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.showError).toHaveBeenCalledWith('Some fields are invalid');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return an error message 'The observation type must be unique'", () => {
|
|
||||||
controller.$scope.form = {};
|
|
||||||
spyOn(controller.vnApp, 'showError').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.showError).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/crudTicketObservation`).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/crudTicketObservation`).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/crudTicketObservation`).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, 'showError').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.showError).toHaveBeenCalledWith('No changes to save');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,17 +1,16 @@
|
||||||
<vn-crud-model
|
<vn-crud-model
|
||||||
vn-id="model"
|
vn-id="model"
|
||||||
url="/ticket/api/TicketPackagings"
|
url="/ticket/api/TicketPackagings"
|
||||||
|
fields="['id', 'ticketFk', 'packagingFk', 'quantity', 'created']"
|
||||||
link="{ticketFk: $ctrl.$stateParams.id}"
|
link="{ticketFk: $ctrl.$stateParams.id}"
|
||||||
data="packages" on-data-change="$ctrl.getPackages()">
|
data="packages" on-data-change="$ctrl.onDataChange()">
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
|
|
||||||
<vn-watcher
|
<vn-watcher
|
||||||
vn-id="watcher"
|
vn-id="watcher"
|
||||||
data="packages"
|
data="packages"
|
||||||
form="form">
|
form="form">
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
|
<form name="form" ng-submit="$ctrl.onSubmit()">
|
||||||
<form name="form" ng-submit="$ctrl.submit()">
|
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Packages</vn-title>
|
<vn-title>Packages</vn-title>
|
||||||
<vn-one>
|
<vn-one>
|
||||||
|
@ -45,7 +44,7 @@
|
||||||
medium-grey
|
medium-grey
|
||||||
vn-tooltip="Remove package"
|
vn-tooltip="Remove package"
|
||||||
icon="remove_circle_outline"
|
icon="remove_circle_outline"
|
||||||
ng-click="$ctrl.removePackage($index)">
|
ng-click="model.remove($index)">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
@ -56,7 +55,7 @@
|
||||||
vn-tooltip="Add package"
|
vn-tooltip="Add package"
|
||||||
vn-bind="+"
|
vn-bind="+"
|
||||||
icon="add_circle"
|
icon="add_circle"
|
||||||
ng-click="$ctrl.addPackage()">
|
ng-click="$ctrl.add()">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
|
|
|
@ -1,80 +1,32 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor($http, $scope, $stateParams, $translate, vnApp) {
|
constructor($scope, $stateParams) {
|
||||||
this.$http = $http;
|
|
||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
this.$stateParams = $stateParams;
|
this.$stateParams = $stateParams;
|
||||||
this.$translate = $translate;
|
|
||||||
this.vnApp = vnApp;
|
|
||||||
this.removedPackages = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
add() {
|
||||||
let query = `/ticket/api/TicketPackagings/crud`;
|
this.$scope.model.insert({
|
||||||
let packagesObj = {
|
packagingFk: null,
|
||||||
delete: this.removedPackages,
|
quantity: null,
|
||||||
create: [],
|
created: new Date(),
|
||||||
update: []
|
ticketFk: this.$stateParams.id
|
||||||
};
|
|
||||||
|
|
||||||
this.packages.forEach(item => {
|
|
||||||
if (typeof item.id === 'undefined')
|
|
||||||
packagesObj.create.push(item);
|
|
||||||
|
|
||||||
if (typeof item.id !== 'undefined' && !this.packageEquals(item, this.oldPackages[item.id]))
|
|
||||||
packagesObj.update.push(item);
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
this.$scope.watcher.check();
|
this.$scope.watcher.check();
|
||||||
|
this.$scope.model.save().then(() => {
|
||||||
this.$http.post(query, packagesObj).then(res => {
|
|
||||||
this.$scope.watcher.notifySaved();
|
this.$scope.watcher.notifySaved();
|
||||||
this.$scope.model.refresh();
|
this.$scope.model.refresh();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removePackage(index) {
|
|
||||||
if (this.packages[index] && this.packages[index].id)
|
|
||||||
this.removedPackages.push(this.packages[index].id);
|
|
||||||
|
|
||||||
this.packages.splice(index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
addPackage() {
|
|
||||||
let data = {
|
|
||||||
packagingFk: null,
|
|
||||||
quantity: null,
|
|
||||||
created: Date.now(),
|
|
||||||
ticketFk: this.ticket.id
|
|
||||||
};
|
|
||||||
this.packages.push(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
getPackages() {
|
|
||||||
this.packages = this.$scope.model.data;
|
|
||||||
this.setOldPackages();
|
|
||||||
}
|
|
||||||
|
|
||||||
setOldPackages() {
|
|
||||||
this.oldPackages = [];
|
|
||||||
this.removedPackages = [];
|
|
||||||
this.packages.forEach(item => {
|
|
||||||
this.oldPackages[item.id] = Object.assign({}, item);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
packageEquals(newPackage, oldPackage) {
|
|
||||||
return newPackage.packagingFk === oldPackage.packagingFk && newPackage.quantity == oldPackage.quantity;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$http', '$scope', '$stateParams', '$translate', 'vnApp'];
|
Controller.$inject = ['$scope', '$stateParams'];
|
||||||
|
|
||||||
ngModule.component('vnTicketPackageIndex', {
|
ngModule.component('vnTicketPackageIndex', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Controller,
|
controller: Controller
|
||||||
bindings: {
|
|
||||||
ticket: '<'
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Ticket', () => {
|
|
||||||
describe('Component vnTicketPackageIndex', () => {
|
|
||||||
let $componentController;
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
let $scope;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
angular.mock.module('ticket');
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_, $rootScope) => {
|
|
||||||
$componentController = _$componentController_;
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
|
||||||
$scope = {
|
|
||||||
model: {
|
|
||||||
refresh: () => {}
|
|
||||||
},
|
|
||||||
watcher: {
|
|
||||||
check: () => {},
|
|
||||||
notifySaved: () => {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
controller = $componentController('vnTicketPackageIndex', {$scope: $scope});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('removePackage()', () => {
|
|
||||||
it('should push a package to removedPackages in the controller', () => {
|
|
||||||
controller.packages = [{id: 1}, {id: 2}];
|
|
||||||
controller.removePackage(0);
|
|
||||||
|
|
||||||
expect(controller.removedPackages).toEqual([1]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('submit()', () => {
|
|
||||||
it('should perform a post', () => {
|
|
||||||
spyOn(controller.$scope.watcher, 'notifySaved');
|
|
||||||
spyOn(controller.$scope.model, 'refresh');
|
|
||||||
|
|
||||||
controller.removedPackages = [];
|
|
||||||
controller.oldPackages = [];
|
|
||||||
controller.oldPackages[1] = {id: 1, packagingFk: 1, quantity: 5, ticketFk: 1};
|
|
||||||
controller.packages = [
|
|
||||||
{quantity: 5, packagingFk: 2, ticketFk: 1},
|
|
||||||
{id: 1, packagingFk: 1, quantity: 25, ticketFk: 1}
|
|
||||||
];
|
|
||||||
|
|
||||||
let data = {
|
|
||||||
delete: [],
|
|
||||||
create: [{quantity: 5, packagingFk: 2, ticketFk: 1}],
|
|
||||||
update: [{id: 1, packagingFk: 1, quantity: 25, ticketFk: 1}]
|
|
||||||
};
|
|
||||||
|
|
||||||
$httpBackend.when('POST', '/ticket/api/TicketPackagings/crud', data).respond(200);
|
|
||||||
$httpBackend.expect('POST', '/ticket/api/TicketPackagings/crud', data).respond('ok');
|
|
||||||
controller.submit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$scope.model.refresh).toHaveBeenCalledWith();
|
|
||||||
expect(controller.$scope.watcher.notifySaved).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('packageEquals()', () => {
|
|
||||||
it('should return true if the old package and the new one matches', () => {
|
|
||||||
let oldPackage = {quantity: 5, packagingFk: 2};
|
|
||||||
let newPackage = {quantity: 5, packagingFk: 2};
|
|
||||||
|
|
||||||
let result = controller.packageEquals(oldPackage, newPackage);
|
|
||||||
|
|
||||||
expect(result).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should return false if the old package and the new one doesn't match`, () => {
|
|
||||||
let oldPackage = {quantity: 5, packagingFk: 2};
|
|
||||||
let newPackage = {quantity: 6, packagingFk: 2};
|
|
||||||
|
|
||||||
let result = controller.packageEquals(oldPackage, newPackage);
|
|
||||||
|
|
||||||
expect(result).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -3,7 +3,6 @@ export * from './module';
|
||||||
import './search-panel';
|
import './search-panel';
|
||||||
import './index';
|
import './index';
|
||||||
import './card';
|
import './card';
|
||||||
import './descriptor';
|
|
||||||
import './summary';
|
import './summary';
|
||||||
import './data';
|
import './data';
|
||||||
import './data/step-one';
|
import './data/step-one';
|
||||||
|
|
|
@ -37,6 +37,6 @@
|
||||||
</vn-pagination>
|
</vn-pagination>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
<a ui-sref="ticket.card.tracking.edit" vn-bind="+" vn-visible-by="production" fixed-bottom-right>
|
<a ui-sref="ticket.card.tracking.edit" vn-bind="+" vn-visible-by="production, administrative" fixed-bottom-right>
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
<vn-float-button icon="add"></vn-float-button>
|
||||||
</a>
|
</a>
|
|
@ -195,27 +195,22 @@ export default {
|
||||||
tagsButton: `vn-menu-item a[ui-sref="item.card.tags"]`,
|
tagsButton: `vn-menu-item a[ui-sref="item.card.tags"]`,
|
||||||
firstRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(2) vn-icon-button[icon="remove_circle_outline"]`,
|
firstRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(2) vn-icon-button[icon="remove_circle_outline"]`,
|
||||||
firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||||
firstTagDisabled: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete > div > div > input`,
|
|
||||||
firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
firstValueInput: `vn-item-tags vn-horizontal:nth-child(2) > vn-textfield[label="Value"] input`,
|
firstValueInput: `vn-item-tags vn-horizontal:nth-child(2) > vn-textfield[label="Value"] input`,
|
||||||
firstRelevancyInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Relevancy"] input`,
|
firstRelevancyInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Relevancy"] input`,
|
||||||
secondTagSelect: `vn-item-tags vn-horizontal:nth-child(3) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
secondTagSelect: `vn-item-tags vn-horizontal:nth-child(3) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||||
secondTagDisabled: `vn-item-tags vn-horizontal:nth-child(3) > vn-autocomplete > div > div > input`,
|
|
||||||
secondTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(3) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
secondTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(3) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
secondValueInput: `vn-item-tags vn-horizontal:nth-child(3) > vn-textfield[label="Value"] input`,
|
secondValueInput: `vn-item-tags vn-horizontal:nth-child(3) > vn-textfield[label="Value"] input`,
|
||||||
secondRelevancyInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Relevancy"] input`,
|
secondRelevancyInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Relevancy"] input`,
|
||||||
thirdTagSelect: `vn-item-tags vn-horizontal:nth-child(4) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
thirdTagSelect: `vn-item-tags vn-horizontal:nth-child(4) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||||
thirdTagDisabled: `vn-item-tags vn-horizontal:nth-child(4) > vn-autocomplete > div > div > input`,
|
|
||||||
thirdTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(4) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
thirdTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(4) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
thirdValueInput: `vn-item-tags vn-horizontal:nth-child(4) > vn-textfield[label="Value"] input`,
|
thirdValueInput: `vn-item-tags vn-horizontal:nth-child(4) > vn-textfield[label="Value"] input`,
|
||||||
thirdRelevancyInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Relevancy"] input`,
|
thirdRelevancyInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Relevancy"] input`,
|
||||||
fourthTagSelect: `vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
fourthTagSelect: `vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||||
fourthTagDisabled: `vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete > div > div > input`,
|
|
||||||
fourthTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
fourthTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
fourthValueInput: `vn-item-tags vn-horizontal:nth-child(5) > vn-textfield[label="Value"] input`,
|
fourthValueInput: `vn-item-tags vn-horizontal:nth-child(5) > vn-textfield[label="Value"] input`,
|
||||||
fourthRelevancyInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Relevancy"] input`,
|
fourthRelevancyInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Relevancy"] input`,
|
||||||
fifthTagSelect: `vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
fifthTagSelect: `vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||||
fifthTagDisabled: `vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete > div > div > input`,
|
|
||||||
fifthValueInput: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Value"] input`,
|
fifthValueInput: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Value"] input`,
|
||||||
fifthRelevancyInput: `vn-horizontal:nth-child(6) > vn-textfield[label="Relevancy"] input`,
|
fifthRelevancyInput: `vn-horizontal:nth-child(6) > vn-textfield[label="Relevancy"] input`,
|
||||||
seventhTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(8) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(5)`,
|
seventhTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(8) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(5)`,
|
||||||
|
@ -240,22 +235,19 @@ export default {
|
||||||
addBarcodeButton: `vn-icon[icon="add_circle"]`,
|
addBarcodeButton: `vn-icon[icon="add_circle"]`,
|
||||||
thirdCodeInput: `vn-item-barcode vn-horizontal:nth-child(4) > ${components.vnTextfield}`,
|
thirdCodeInput: `vn-item-barcode vn-horizontal:nth-child(4) > ${components.vnTextfield}`,
|
||||||
submitBarcodesButton: `${components.vnSubmit}`,
|
submitBarcodesButton: `${components.vnSubmit}`,
|
||||||
firstCodeRemoveButton: `vn-horizontal:nth-child(2) > vn-icon[icon="remove_circle_outline"]`
|
firstCodeRemoveButton: `vn-item-barcode vn-horizontal vn-none vn-icon[icon="remove_circle_outline"]`
|
||||||
},
|
},
|
||||||
itemNiches: {
|
itemNiches: {
|
||||||
nicheButton: `vn-menu-item a[ui-sref="item.card.niche"]`,
|
nicheButton: `vn-menu-item a[ui-sref="item.card.niche"]`,
|
||||||
addNicheButton: `vn-icon[icon="add_circle"]`,
|
addNicheButton: `vn-icon[icon="add_circle"]`,
|
||||||
firstWarehouseSelect: `vn-autocomplete[field="itemNiche.warehouseFk"] input`,
|
firstWarehouseSelect: `vn-autocomplete[field="niche.warehouseFk"] input`,
|
||||||
firstWarehouseDisabled: `vn-horizontal:nth-child(2) > vn-textfield[label="Warehouse"] input`,
|
firstWarehouseSelectSecondOption: `vn-autocomplete[field="niche.warehouseFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
firstWarehouseSelectSecondOption: `vn-autocomplete[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(2)`,
|
|
||||||
firstCodeInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Code"] input`,
|
firstCodeInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Code"] input`,
|
||||||
secondWarehouseSelect: `vn-horizontal:nth-child(3) > vn-autocomplete[field="itemNiche.warehouseFk"] input`,
|
secondWarehouseSelect: `vn-horizontal:nth-child(3) > vn-autocomplete[field="niche.warehouseFk"] input`,
|
||||||
secondWarehouseDisabled: `vn-horizontal:nth-child(3) > vn-textfield[label="Warehouse"] input`,
|
|
||||||
secondCodeInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Code"] input`,
|
secondCodeInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Code"] input`,
|
||||||
secondNicheRemoveButton: `vn-horizontal:nth-child(3) > vn-icon[icon="remove_circle_outline"]`,
|
secondNicheRemoveButton: `vn-horizontal:nth-child(3) > vn-none > vn-icon[icon="remove_circle_outline"]`,
|
||||||
thirdWarehouseSelect: `vn-horizontal:nth-child(4) > vn-autocomplete[field="itemNiche.warehouseFk"] input`,
|
thirdWarehouseSelect: `vn-horizontal:nth-child(4) > vn-autocomplete[field="niche.warehouseFk"] input`,
|
||||||
thirdWarehouseDisabled: `vn-horizontal:nth-child(4) > vn-textfield[label="Warehouse"] input`,
|
thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > vn-autocomplete[field="niche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`,
|
||||||
thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > vn-autocomplete[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`,
|
|
||||||
thirdCodeInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Code"] input`,
|
thirdCodeInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Code"] input`,
|
||||||
submitNichesButton: `${components.vnSubmit}`
|
submitNichesButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
|
@ -288,9 +280,8 @@ export default {
|
||||||
notesButton: `vn-menu-item a[ui-sref="ticket.card.observation"]`,
|
notesButton: `vn-menu-item a[ui-sref="ticket.card.observation"]`,
|
||||||
firstNoteRemoveButton: `vn-icon[icon="remove_circle_outline"]`,
|
firstNoteRemoveButton: `vn-icon[icon="remove_circle_outline"]`,
|
||||||
addNoteButton: `vn-icon[icon="add_circle"]`,
|
addNoteButton: `vn-icon[icon="add_circle"]`,
|
||||||
firstNoteSelect: `vn-autocomplete[field="ticketObservation.observationTypeFk"] input`,
|
firstNoteSelect: `vn-autocomplete[field="observation.observationTypeFk"] input`,
|
||||||
firstNoteSelectSecondOption: `vn-autocomplete[field="ticketObservation.observationTypeFk"] vn-drop-down ul > li:nth-child(2)`,
|
firstNoteSelectSecondOption: `vn-autocomplete[field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
firstNoteDisabled: `vn-textfield[label="Observation type"] input`,
|
|
||||||
firstDescriptionInput: `vn-textfield[label="Description"] input`,
|
firstDescriptionInput: `vn-textfield[label="Description"] input`,
|
||||||
submitNotesButton: `${components.vnSubmit}`
|
submitNotesButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
|
|
|
@ -65,10 +65,10 @@ describe('Item', () => {
|
||||||
.click(selectors.itemBasicData.basicDataButton)
|
.click(selectors.itemBasicData.basicDataButton)
|
||||||
.wait(selectors.itemBasicData.nameInput)
|
.wait(selectors.itemBasicData.nameInput)
|
||||||
.click(selectors.itemTags.tagsButton)
|
.click(selectors.itemTags.tagsButton)
|
||||||
.waitForTextInInput(selectors.itemTags.firstTagDisabled, 'Diámetro')
|
.waitForTextInInput(selectors.itemTags.firstTagSelect, 'Ancho de la base')
|
||||||
.getInputValue(selectors.itemTags.firstTagDisabled)
|
.getInputValue(selectors.itemTags.firstTagSelect)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toEqual('Diámetro');
|
expect(result).toEqual('Ancho de la base');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -92,8 +92,8 @@ describe('Item', () => {
|
||||||
|
|
||||||
it(`should confirm the second select is the expected one`, () => {
|
it(`should confirm the second select is the expected one`, () => {
|
||||||
return nightmare
|
return nightmare
|
||||||
.waitForTextInInput(selectors.itemTags.secondTagDisabled, 'Variedad')
|
.waitForTextInInput(selectors.itemTags.secondTagSelect, 'Variedad')
|
||||||
.getInputValue(selectors.itemTags.secondTagDisabled)
|
.getInputValue(selectors.itemTags.secondTagSelect)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toEqual('Variedad');
|
expect(result).toEqual('Variedad');
|
||||||
});
|
});
|
||||||
|
@ -119,8 +119,8 @@ describe('Item', () => {
|
||||||
|
|
||||||
it(`should confirm the third select is the expected one`, () => {
|
it(`should confirm the third select is the expected one`, () => {
|
||||||
return nightmare
|
return nightmare
|
||||||
.waitForTextInInput(selectors.itemTags.thirdTagDisabled, 'Longitud(cm)')
|
.waitForTextInInput(selectors.itemTags.thirdTagSelect, 'Longitud(cm)')
|
||||||
.getInputValue(selectors.itemTags.thirdTagDisabled)
|
.getInputValue(selectors.itemTags.thirdTagSelect)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toEqual('Longitud(cm)');
|
expect(result).toEqual('Longitud(cm)');
|
||||||
});
|
});
|
||||||
|
@ -146,8 +146,8 @@ describe('Item', () => {
|
||||||
|
|
||||||
it(`should confirm the fourth select is the expected one`, () => {
|
it(`should confirm the fourth select is the expected one`, () => {
|
||||||
return nightmare
|
return nightmare
|
||||||
.waitForTextInInput(selectors.itemTags.fourthTagDisabled, 'Proveedor')
|
.waitForTextInInput(selectors.itemTags.fourthTagSelect, 'Proveedor')
|
||||||
.getInputValue(selectors.itemTags.fourthTagDisabled)
|
.getInputValue(selectors.itemTags.fourthTagSelect)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toEqual('Proveedor');
|
expect(result).toEqual('Proveedor');
|
||||||
});
|
});
|
||||||
|
@ -173,8 +173,8 @@ describe('Item', () => {
|
||||||
|
|
||||||
it(`should confirm the fifth select is the expected one`, () => {
|
it(`should confirm the fifth select is the expected one`, () => {
|
||||||
return nightmare
|
return nightmare
|
||||||
.waitForTextInInput(selectors.itemTags.fifthTagDisabled, 'Color')
|
.waitForTextInInput(selectors.itemTags.fifthTagSelect, 'Color')
|
||||||
.getInputValue(selectors.itemTags.fifthTagDisabled)
|
.getInputValue(selectors.itemTags.fifthTagSelect)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toEqual('Color');
|
expect(result).toEqual('Color');
|
||||||
});
|
});
|
||||||
|
|
|
@ -63,8 +63,8 @@ describe('Item', () => {
|
||||||
.click(selectors.itemBasicData.basicDataButton)
|
.click(selectors.itemBasicData.basicDataButton)
|
||||||
.wait(selectors.itemBasicData.nameInput)
|
.wait(selectors.itemBasicData.nameInput)
|
||||||
.click(selectors.itemNiches.nicheButton)
|
.click(selectors.itemNiches.nicheButton)
|
||||||
.waitForTextInInput(selectors.itemNiches.firstWarehouseDisabled, 'Warehouse One')
|
.waitForTextInInput(selectors.itemNiches.firstWarehouseSelect, 'Warehouse One')
|
||||||
.getInputValue(selectors.itemNiches.firstWarehouseDisabled)
|
.getInputValue(selectors.itemNiches.firstWarehouseSelect)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toEqual('Warehouse One');
|
expect(result).toEqual('Warehouse One');
|
||||||
return nightmare
|
return nightmare
|
||||||
|
@ -77,7 +77,7 @@ describe('Item', () => {
|
||||||
|
|
||||||
it(`should confirm the second niche is the expected one`, () => {
|
it(`should confirm the second niche is the expected one`, () => {
|
||||||
return nightmare
|
return nightmare
|
||||||
.getInputValue(selectors.itemNiches.secondWarehouseDisabled)
|
.getInputValue(selectors.itemNiches.secondWarehouseSelect)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toEqual('Warehouse Three');
|
expect(result).toEqual('Warehouse Three');
|
||||||
return nightmare
|
return nightmare
|
||||||
|
@ -90,9 +90,9 @@ describe('Item', () => {
|
||||||
|
|
||||||
it(`should confirm the third niche is the expected one`, () => {
|
it(`should confirm the third niche is the expected one`, () => {
|
||||||
return nightmare
|
return nightmare
|
||||||
.getInputValue(selectors.itemNiches.thirdWarehouseDisabled)
|
.getInputValue(selectors.itemNiches.thirdWarehouseSelect)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toEqual('Warehouse Four');
|
expect(result).toEqual('Warehouse Two');
|
||||||
return nightmare
|
return nightmare
|
||||||
.getInputValue(selectors.itemNiches.thirdCodeInput);
|
.getInputValue(selectors.itemNiches.thirdCodeInput);
|
||||||
})
|
})
|
||||||
|
|
|
@ -64,8 +64,8 @@ describe('Ticket', () => {
|
||||||
.click(selectors.ticketPackages.packagesButton)
|
.click(selectors.ticketPackages.packagesButton)
|
||||||
.wait(selectors.ticketPackages.firstPackageSelect)
|
.wait(selectors.ticketPackages.firstPackageSelect)
|
||||||
.click(selectors.ticketNotes.notesButton)
|
.click(selectors.ticketNotes.notesButton)
|
||||||
.waitForTextInInput(selectors.ticketNotes.firstNoteDisabled, 'observation two')
|
.waitForTextInInput(selectors.ticketNotes.firstNoteSelect, 'observation two')
|
||||||
.getInputValue(selectors.ticketNotes.firstNoteDisabled)
|
.getInputValue(selectors.ticketNotes.firstNoteSelect)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toEqual('observation two');
|
expect(result).toEqual('observation two');
|
||||||
return nightmare
|
return nightmare
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
// Validations
|
||||||
|
|
||||||
|
Self.validatesUniquenessOf('saleFk', {
|
||||||
|
message: `A claim with that sale already exists`
|
||||||
|
});
|
||||||
|
};
|
|
@ -1,3 +1,7 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/item-barcode/crudItemBarcodes')(Self);
|
require('../methods/item-barcode/crudItemBarcodes')(Self);
|
||||||
|
|
||||||
|
Self.validatesUniquenessOf('code', {
|
||||||
|
message: `Barcode must be unique`
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/item-niche/crudItemNiches')(Self);
|
/* Self.validateAsync('warehouseFk', validateWarehouseUniqueness, {
|
||||||
|
message: `The warehouse can't be repeated`
|
||||||
|
});
|
||||||
|
|
||||||
|
async function validateWarehouseUniqueness(err, done) {
|
||||||
|
let where = {
|
||||||
|
itemFk: this.itemFk,
|
||||||
|
warehouseFk: this.warehouseFk
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.id != null)
|
||||||
|
where.id = {neq: this.id};
|
||||||
|
|
||||||
|
let warehouseExists = await Self.findOne({where: where});
|
||||||
|
console.log(warehouseExists);
|
||||||
|
|
||||||
|
if (warehouseExists)
|
||||||
|
err();
|
||||||
|
|
||||||
|
done();
|
||||||
|
} */
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,29 +1,38 @@
|
||||||
{
|
{
|
||||||
"name": "ItemNiche",
|
"name": "ItemNiche",
|
||||||
"base": "VnModel",
|
"base": "VnModel",
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"table": "itemPlacement",
|
"table": "itemPlacement",
|
||||||
"database": "vn"
|
"database": "vn"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"properties": {
|
|
||||||
"code": {
|
|
||||||
"type": "String",
|
|
||||||
"required": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"relations": {
|
|
||||||
"item": {
|
|
||||||
"type": "belongsTo",
|
|
||||||
"model": "Item",
|
|
||||||
"foreignKey": "itemFk"
|
|
||||||
},
|
},
|
||||||
"warehouse": {
|
"properties": {
|
||||||
"type": "belongsTo",
|
"id": {
|
||||||
"model": "Warehouse",
|
"type": "Number",
|
||||||
"foreignKey": "warehouseFk",
|
"id": 1,
|
||||||
"required": true
|
"description": "Identifier"
|
||||||
}
|
},
|
||||||
}
|
"warehouseFk": {
|
||||||
|
"type": "Number",
|
||||||
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"item": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Item",
|
||||||
|
"foreignKey": "itemFk"
|
||||||
|
},
|
||||||
|
"warehouse": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Warehouse",
|
||||||
|
"foreignKey": "warehouseFk",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,5 +30,6 @@
|
||||||
"The grade must be an integer greater than or equal to zero": "The grade must be an integer greater than or equal to zero",
|
"The grade must be an integer greater than or equal to zero": "The grade must be an integer greater than or equal to zero",
|
||||||
"Sample type cannot be blank": "Sample type cannot be blank",
|
"Sample type cannot be blank": "Sample type cannot be blank",
|
||||||
"The new quantity should be smaller than the old one": "La nueva cantidad debe ser menor que la anterior",
|
"The new quantity should be smaller than the old one": "La nueva cantidad debe ser menor que la anterior",
|
||||||
"The package cannot be blank": "The package cannot be blank"
|
"The package cannot be blank": "The package cannot be blank",
|
||||||
|
"The warehouse can't be repeated": "The warehouse can't be repeated"
|
||||||
}
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue