Compare commits
2 Commits
dev
...
7401-redir
Author | SHA1 | Date |
---|---|---|
Pablo Natek | 1ee0592096 | |
Pablo Natek | d16130edc3 |
|
@ -1,52 +0,0 @@
|
||||||
<div class="search-panel">
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Agencies"
|
|
||||||
data="agencies">
|
|
||||||
</vn-crud-model>
|
|
||||||
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pt-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="General search"
|
|
||||||
ng-model="filter.search"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
url="AgencyModes"
|
|
||||||
label="Agency route"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
ng-model="filter.agencyModeFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
data="agencies"
|
|
||||||
label="Agency Agreement"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
ng-model="filter.agencyFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<section class="vn-px-md">
|
|
||||||
<vn-horizontal class="manifold-panel vn-pa-md">
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="From"
|
|
||||||
ng-model="filter.from"
|
|
||||||
on-change="$ctrl.from = value">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="To"
|
|
||||||
ng-model="filter.to"
|
|
||||||
on-change="$ctrl.to = value">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
</section>
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pb-lg vn-mt-lg">
|
|
||||||
<vn-submit label="Search"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,17 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
|
|
||||||
class Controller extends SearchPanel {
|
|
||||||
get filter() {
|
|
||||||
return this.$.filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
set filter(value = {}) {
|
|
||||||
this.$.filter = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnAgencyTermSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,2 +0,0 @@
|
||||||
Search by invoiceIn id or autonomous name: Buscar por id de recibida o por nombre de autónomo
|
|
||||||
Search autonomous: Buscar autónomos
|
|
|
@ -1,108 +0,0 @@
|
||||||
<mg-ajax path="dms/upload" options="vnPost"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.dms">
|
|
||||||
</vn-watcher>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Companies"
|
|
||||||
data="companies"
|
|
||||||
order="code">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Warehouses"
|
|
||||||
data="warehouses"
|
|
||||||
order="name">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="DmsTypes"
|
|
||||||
data="dmsTypes"
|
|
||||||
order="name">
|
|
||||||
</vn-crud-model>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="$ctrl.onSubmit()"
|
|
||||||
class="vn-ma-md"
|
|
||||||
enctype="multipart/form-data">
|
|
||||||
<div class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
vn-focus
|
|
||||||
label="Reference"
|
|
||||||
ng-model="$ctrl.dms.reference"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
label="Company"
|
|
||||||
ng-model="$ctrl.dms.companyId"
|
|
||||||
data="companies"
|
|
||||||
show-field="code"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="$ctrl.dms.warehouseId"
|
|
||||||
data="warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
label="Type"
|
|
||||||
ng-model="$ctrl.dms.dmsTypeId"
|
|
||||||
data="dmsTypes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textarea
|
|
||||||
vn-one
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.dms.description"
|
|
||||||
rule>
|
|
||||||
</vn-textarea>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-file
|
|
||||||
vn-one
|
|
||||||
label="File"
|
|
||||||
ng-model="$ctrl.dms.files"
|
|
||||||
on-change="$ctrl.onFileChange($files)"
|
|
||||||
accept="{{$ctrl.allowedContentTypes}}"
|
|
||||||
required="true"
|
|
||||||
multiple="true">
|
|
||||||
<append>
|
|
||||||
<vn-icon vn-none
|
|
||||||
color-marginal
|
|
||||||
title="{{$ctrl.contentTypesInfo}}"
|
|
||||||
icon="info">
|
|
||||||
</vn-icon>
|
|
||||||
</append>
|
|
||||||
</vn-input-file>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-check
|
|
||||||
label="Generate identifier for original file"
|
|
||||||
ng-model="$ctrl.dms.hasFile">
|
|
||||||
</vn-check>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Upload">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="client.card.dms.index">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
|
@ -1,120 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
import UserError from 'core/lib/user-error';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
this.dms = {
|
|
||||||
files: [],
|
|
||||||
hasFile: false,
|
|
||||||
hasFileAttached: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
get route() {
|
|
||||||
return this._route;
|
|
||||||
}
|
|
||||||
|
|
||||||
set route(value) {
|
|
||||||
this._route = value;
|
|
||||||
|
|
||||||
this.setDefaultParams();
|
|
||||||
this.getAllowedContentTypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
$onChanges() {
|
|
||||||
if (this.$params && this.$params.q)
|
|
||||||
this.params = JSON.parse(this.$params.q);
|
|
||||||
}
|
|
||||||
|
|
||||||
getAllowedContentTypes() {
|
|
||||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
|
||||||
const contentTypes = res.data.join(', ');
|
|
||||||
this.allowedContentTypes = contentTypes;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get contentTypesInfo() {
|
|
||||||
return this.$t('ContentTypesInfo', {
|
|
||||||
allowedContentTypes: this.allowedContentTypes
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setDefaultParams() {
|
|
||||||
const params = {filter: {
|
|
||||||
where: {code: 'invoiceIn'}
|
|
||||||
}};
|
|
||||||
this.$http.get('DmsTypes/findOne', {params}).then(res => {
|
|
||||||
const dmsType = res.data && res.data;
|
|
||||||
const companyId = this.vnConfig.companyFk;
|
|
||||||
const warehouseId = this.vnConfig.warehouseFk;
|
|
||||||
const defaultParams = {
|
|
||||||
warehouseId: warehouseId,
|
|
||||||
companyId: companyId,
|
|
||||||
dmsTypeId: dmsType.id,
|
|
||||||
description: this.params.supplierName
|
|
||||||
};
|
|
||||||
|
|
||||||
this.dms = Object.assign(this.dms, defaultParams);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
if (this.dms.files.length > 1) throw new UserError('You cannot attach more than one document');
|
|
||||||
const query = `dms/uploadFile`;
|
|
||||||
const options = {
|
|
||||||
method: 'POST',
|
|
||||||
url: query,
|
|
||||||
params: this.dms,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': undefined
|
|
||||||
},
|
|
||||||
transformRequest: files => {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(files[0].name, files[0]);
|
|
||||||
return formData;
|
|
||||||
},
|
|
||||||
data: this.dms.files
|
|
||||||
};
|
|
||||||
this.$http(options).then(res => {
|
|
||||||
if (res) {
|
|
||||||
const addedDms = res.data;
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
rows: this.params.rows,
|
|
||||||
dms: addedDms
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http.post('AgencyTerms/createInvoiceIn', params)
|
|
||||||
.then(() => {
|
|
||||||
this.$state.go('route.agencyTerm.index');
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onFileChange(files) {
|
|
||||||
let hasFileAttached = false;
|
|
||||||
|
|
||||||
if (files.length > 0)
|
|
||||||
hasFileAttached = true;
|
|
||||||
|
|
||||||
this.$.$applyAsync(() => {
|
|
||||||
this.dms.hasFileAttached = hasFileAttached;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnAgencyTermCreateInvoiceIn', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
route: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,107 +0,0 @@
|
||||||
import './index';
|
|
||||||
import watcher from 'core/mocks/watcher.js';
|
|
||||||
|
|
||||||
describe('AgencyTerm', () => {
|
|
||||||
describe('Component vnAgencyTermCreateInvoiceIn', () => {
|
|
||||||
let controller;
|
|
||||||
let $scope;
|
|
||||||
let $httpBackend;
|
|
||||||
let $httpParamSerializer;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpParamSerializer = _$httpParamSerializer_;
|
|
||||||
const $element = angular.element('<vn-agency-term-create-invoice-in></vn-agency-term-create-invoice-in>');
|
|
||||||
controller = $componentController('vnAgencyTermCreateInvoiceIn', {$element});
|
|
||||||
controller._route = {
|
|
||||||
id: 1
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('$onChanges()', () => {
|
|
||||||
it('should update the params data when $params.q is defined', () => {
|
|
||||||
controller.$params = {q: '{"supplierName": "Plants SL","rows": null}'};
|
|
||||||
|
|
||||||
const params = {q: '{"supplierName": "Plants SL", "rows": null}'};
|
|
||||||
const json = JSON.parse(params.q);
|
|
||||||
|
|
||||||
controller.$onChanges();
|
|
||||||
|
|
||||||
expect(controller.params).toEqual(json);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('route() setter', () => {
|
|
||||||
it('should set the ticket data and then call setDefaultParams() and getAllowedContentTypes()', () => {
|
|
||||||
jest.spyOn(controller, 'setDefaultParams');
|
|
||||||
jest.spyOn(controller, 'getAllowedContentTypes');
|
|
||||||
controller.route = {
|
|
||||||
id: 1
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(controller.route).toBeDefined();
|
|
||||||
expect(controller.setDefaultParams).toHaveBeenCalledWith();
|
|
||||||
expect(controller.getAllowedContentTypes).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getAllowedContentTypes()', () => {
|
|
||||||
it('should make an HTTP GET request to get the allowed content types', () => {
|
|
||||||
const expectedResponse = ['image/png', 'image/jpg'];
|
|
||||||
$httpBackend.expect('GET', `DmsContainers/allowedContentTypes`).respond(expectedResponse);
|
|
||||||
controller.getAllowedContentTypes();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.allowedContentTypes).toBeDefined();
|
|
||||||
expect(controller.allowedContentTypes).toEqual('image/png, image/jpg');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setDefaultParams()', () => {
|
|
||||||
it('should perform a GET query and define the dms property on controller', () => {
|
|
||||||
const params = {filter: {
|
|
||||||
where: {code: 'invoiceIn'}
|
|
||||||
}};
|
|
||||||
const serializedParams = $httpParamSerializer(params);
|
|
||||||
$httpBackend.expect('GET', `DmsTypes/findOne?${serializedParams}`).respond({id: 1, code: 'invoiceIn'});
|
|
||||||
controller.params = {supplierName: 'Plants SL'};
|
|
||||||
controller.setDefaultParams();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.dms).toBeDefined();
|
|
||||||
expect(controller.dms.dmsTypeId).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onSubmit()', () => {
|
|
||||||
it('should make an HTTP POST request to save the form data', () => {
|
|
||||||
controller.$.watcher = watcher;
|
|
||||||
|
|
||||||
jest.spyOn(controller.$.watcher, 'updateOriginalData');
|
|
||||||
const files = [{id: 1, name: 'MyFile'}];
|
|
||||||
controller.dms = {files};
|
|
||||||
const serializedParams = $httpParamSerializer(controller.dms);
|
|
||||||
const query = `dms/uploadFile?${serializedParams}`;
|
|
||||||
controller.params = {rows: null};
|
|
||||||
|
|
||||||
$httpBackend.expect('POST', query).respond({});
|
|
||||||
$httpBackend.expect('POST', 'AgencyTerms/createInvoiceIn').respond({});
|
|
||||||
controller.onSubmit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onFileChange()', () => {
|
|
||||||
it('should set dms hasFileAttached property to true if has any files', () => {
|
|
||||||
const files = [{id: 1, name: 'MyFile'}];
|
|
||||||
controller.onFileChange(files);
|
|
||||||
$scope.$apply();
|
|
||||||
|
|
||||||
expect(controller.dms.hasFileAttached).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,7 +0,0 @@
|
||||||
vn-ticket-request {
|
|
||||||
.vn-textfield {
|
|
||||||
margin: 0!important;
|
|
||||||
max-width: 100px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,152 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="AgencyTerms/filter"
|
|
||||||
data="agencyTerms"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
auto-state="false"
|
|
||||||
panel="vn-agency-term-search-panel"
|
|
||||||
info="Search by invoiceIn id or autonomous name"
|
|
||||||
placeholder="Search autonomous"
|
|
||||||
filter="{}"
|
|
||||||
model="model">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<vn-card>
|
|
||||||
<smart-table
|
|
||||||
model="model"
|
|
||||||
options="$ctrl.smartTableOptions"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
|
||||||
<slot-actions>
|
|
||||||
<div>
|
|
||||||
<div class="totalBox" style="text-align: center;">
|
|
||||||
<h6 translate>Total</h6>
|
|
||||||
<vn-label-value
|
|
||||||
label="Price"
|
|
||||||
value="{{$ctrl.totalPrice | currency: 'EUR': 2}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</slot-actions>
|
|
||||||
<slot-table>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th shrink>
|
|
||||||
<vn-multi-check
|
|
||||||
model="model">
|
|
||||||
</vn-multi-check>
|
|
||||||
</th>
|
|
||||||
<th shrink field="routeFk">
|
|
||||||
<span translate>Id</span>
|
|
||||||
</th>
|
|
||||||
<th field="created">
|
|
||||||
<span translate>Date</span>
|
|
||||||
</th>
|
|
||||||
<th field="agencyModeFk">
|
|
||||||
<span translate>Agency route</span>
|
|
||||||
</th>
|
|
||||||
<th field="agencyFk">
|
|
||||||
<span translate>Agency Agreement</span>
|
|
||||||
</th>
|
|
||||||
<th field="packages">
|
|
||||||
<span translate>Packages</span>
|
|
||||||
</th>
|
|
||||||
<th field="m3">
|
|
||||||
<span translate>M3</span>
|
|
||||||
</th>
|
|
||||||
<th field="kmTotal">
|
|
||||||
<span translate>Km</span>
|
|
||||||
</th>
|
|
||||||
<th field="price">
|
|
||||||
<span translate>Price</span>
|
|
||||||
</th>
|
|
||||||
<th field="invoiceInFk">
|
|
||||||
<span translate>Received</span>
|
|
||||||
</th>
|
|
||||||
<th field="supplierFk">
|
|
||||||
<span translate>Autonomous</span>
|
|
||||||
</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="agencyTerm in agencyTerms">
|
|
||||||
<td shrink>
|
|
||||||
<vn-check
|
|
||||||
ng-model="agencyTerm.checked"
|
|
||||||
vn-click-stop>
|
|
||||||
</vn-check>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span
|
|
||||||
title="{{::agencyTerm.id}}"
|
|
||||||
vn-click-stop="routeDescriptor.show($event, agencyTerm.routeFk)"
|
|
||||||
class="link">
|
|
||||||
{{::agencyTerm.routeFk}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td shrink-date>{{::agencyTerm.created | date:'dd/MM/yyyy'}}</td>
|
|
||||||
<td>{{::agencyTerm.agencyModeName | dashIfEmpty}}</td>
|
|
||||||
<td>{{::agencyTerm.agencyAgreement | dashIfEmpty}}</td>
|
|
||||||
<td>{{::agencyTerm.packages | dashIfEmpty}}</td>
|
|
||||||
<td>{{::agencyTerm.m3 | dashIfEmpty}}</td>
|
|
||||||
<td>{{::agencyTerm.kmTotal | dashIfEmpty}}</td>
|
|
||||||
<td>{{::agencyTerm.price | dashIfEmpty}}</td>
|
|
||||||
<td>
|
|
||||||
<span
|
|
||||||
vn-click-stop="invoiceInDescriptor.show($event, agencyTerm.invoiceInFk)"
|
|
||||||
class="link">
|
|
||||||
{{::agencyTerm.invoiceInFk}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span
|
|
||||||
class="link"
|
|
||||||
vn-click-stop="supplierDescriptor.show($event, agencyTerm.supplierFk)">
|
|
||||||
{{::agencyTerm.supplierName}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(agencyTerm.route)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</slot-table>
|
|
||||||
</smart-table>
|
|
||||||
</vn-card>
|
|
||||||
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-route-summary
|
|
||||||
route="$ctrl.routeSelected">
|
|
||||||
</vn-route-summary>
|
|
||||||
</vn-popup>
|
|
||||||
|
|
||||||
<vn-route-descriptor-popover
|
|
||||||
vn-id="routeDescriptor">
|
|
||||||
</vn-route-descriptor-popover>
|
|
||||||
<vn-supplier-descriptor-popover
|
|
||||||
vn-id="supplierDescriptor">
|
|
||||||
</vn-supplier-descriptor-popover>
|
|
||||||
<vn-invoice-in-descriptor-popover
|
|
||||||
vn-id="invoiceInDescriptor">
|
|
||||||
</vn-invoice-in-descriptor-popover>
|
|
||||||
|
|
||||||
<div fixed-bottom-right>
|
|
||||||
<vn-vertical style="align-items: center;">
|
|
||||||
<vn-button class="round sm vn-mb-sm"
|
|
||||||
icon="icon-invoice-in-create"
|
|
||||||
ng-show="$ctrl.totalChecked > 0"
|
|
||||||
ng-click="$ctrl.createInvoiceIn()"
|
|
||||||
vn-tooltip="Create invoiceIn"
|
|
||||||
tooltip-position="left">
|
|
||||||
</vn-button>
|
|
||||||
</vn-vertical>
|
|
||||||
</div>
|
|
|
@ -1,121 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
|
|
||||||
this.smartTableOptions = {
|
|
||||||
activeButtons: {
|
|
||||||
search: true
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
field: 'agencyModeFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'AgencyModes',
|
|
||||||
showField: 'name',
|
|
||||||
valueField: 'id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'agencyFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'Agencies',
|
|
||||||
showField: 'name',
|
|
||||||
valueField: 'id'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'supplierFk',
|
|
||||||
autocomplete: {
|
|
||||||
url: 'Suppliers',
|
|
||||||
showField: 'name',
|
|
||||||
valueField: 'name',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'agencyModeFk':
|
|
||||||
return {'a.agencyModeFk': value};
|
|
||||||
case 'supplierFk':
|
|
||||||
return {'a.supplierName': value};
|
|
||||||
case 'routeFk':
|
|
||||||
return {'a.routeFk': value};
|
|
||||||
case 'created':
|
|
||||||
case 'agencyFk':
|
|
||||||
case 'packages':
|
|
||||||
case 'm3':
|
|
||||||
case 'kmTotal':
|
|
||||||
case 'price':
|
|
||||||
case 'invoiceInFk':
|
|
||||||
return {[`a.${param}`]: value};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get checked() {
|
|
||||||
const agencyTerms = this.$.model.data || [];
|
|
||||||
const checkedAgencyTerms = [];
|
|
||||||
for (let agencyTerm of agencyTerms) {
|
|
||||||
if (agencyTerm.checked)
|
|
||||||
checkedAgencyTerms.push(agencyTerm);
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkedAgencyTerms;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalChecked() {
|
|
||||||
return this.checked.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalPrice() {
|
|
||||||
let totalPrice = 0;
|
|
||||||
|
|
||||||
if (this.checked.length > 0) {
|
|
||||||
for (let agencyTerm of this.checked)
|
|
||||||
totalPrice += agencyTerm.price;
|
|
||||||
|
|
||||||
return totalPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
preview(route) {
|
|
||||||
this.routeSelected = route;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
createInvoiceIn() {
|
|
||||||
const rowsToCreateInvoiceIn = [];
|
|
||||||
const supplierFk = this.checked[0].supplierFk;
|
|
||||||
|
|
||||||
for (let agencyTerm of this.checked) {
|
|
||||||
let hasSameSupplier = supplierFk == agencyTerm.supplierFk;
|
|
||||||
if (hasSameSupplier) {
|
|
||||||
rowsToCreateInvoiceIn.push({
|
|
||||||
routeFk: agencyTerm.routeFk,
|
|
||||||
supplierFk: agencyTerm.supplierFk,
|
|
||||||
created: agencyTerm.created,
|
|
||||||
totalPrice: this.totalPrice});
|
|
||||||
} else {
|
|
||||||
this.vnApp.showError(this.$t('Two autonomous cannot be counted at the same time'));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const params = JSON.stringify({
|
|
||||||
supplierName: this.checked[0].supplierName,
|
|
||||||
rows: rowsToCreateInvoiceIn
|
|
||||||
});
|
|
||||||
this.$state.go('route.agencyTerm.createInvoiceIn', {q: params});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnAgencyTermIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,94 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
import crudModel from 'core/mocks/crud-model';
|
|
||||||
|
|
||||||
describe('AgencyTerm', () => {
|
|
||||||
describe('Component vnAgencyTermIndex', () => {
|
|
||||||
let controller;
|
|
||||||
let $window;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$window_) => {
|
|
||||||
$window = _$window_;
|
|
||||||
const $element = angular.element('<vn-agency-term-index></vn-agency-term-index>');
|
|
||||||
controller = $componentController('vnAgencyTermIndex', {$element});
|
|
||||||
controller.$.model = crudModel;
|
|
||||||
controller.$.model.data = [
|
|
||||||
{supplierFk: 1, totalPrice: null},
|
|
||||||
{supplierFk: 1},
|
|
||||||
{supplierFk: 2}
|
|
||||||
];
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('checked() getter', () => {
|
|
||||||
it('should return the checked lines', () => {
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
|
|
||||||
const checkedRows = controller.checked;
|
|
||||||
|
|
||||||
const firstCheckedRow = checkedRows[0];
|
|
||||||
|
|
||||||
expect(firstCheckedRow.supplierFk).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('totalCheked() getter', () => {
|
|
||||||
it('should return the total checked lines', () => {
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
|
|
||||||
const checkedRows = controller.totalChecked;
|
|
||||||
|
|
||||||
expect(checkedRows).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('preview()', () => {
|
|
||||||
it('should show the summary dialog', () => {
|
|
||||||
controller.$.summary = {show: () => {}};
|
|
||||||
jest.spyOn(controller.$.summary, 'show');
|
|
||||||
|
|
||||||
let event = new MouseEvent('click', {
|
|
||||||
view: $window,
|
|
||||||
bubbles: true,
|
|
||||||
cancelable: true
|
|
||||||
});
|
|
||||||
const route = {id: 1};
|
|
||||||
|
|
||||||
controller.preview(event, route);
|
|
||||||
|
|
||||||
expect(controller.$.summary.show).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('createInvoiceIn()', () => {
|
|
||||||
it('should throw an error if more than one autonomous are checked', () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showError');
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
data[2].checked = true;
|
|
||||||
|
|
||||||
controller.createInvoiceIn();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the function go() on $state to go to the file management', () => {
|
|
||||||
jest.spyOn(controller.$state, 'go');
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
|
|
||||||
controller.createInvoiceIn();
|
|
||||||
|
|
||||||
delete data[0].checked;
|
|
||||||
const params = JSON.stringify({
|
|
||||||
supplierName: data[0].supplierName,
|
|
||||||
rows: [data[0]]
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(controller.$state.go).toHaveBeenCalledWith('route.agencyTerm.createInvoiceIn', {q: params});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
Agency route: Agencia ruta
|
|
||||||
Agency Agreement: Acuerdo agencia
|
|
||||||
Autonomous: Autónomos
|
|
||||||
Two autonomous cannot be counted at the same time: Dos autonónomos no pueden ser contabilizados al mismo tiempo
|
|
||||||
You cannot attach more than one document: No puedes adjuntar más de un documento
|
|
|
@ -1,96 +0,0 @@
|
||||||
<mg-ajax path="Routes/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.route"
|
|
||||||
form="form"
|
|
||||||
save="patch">
|
|
||||||
</vn-watcher>
|
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-worker-autocomplete
|
|
||||||
ng-model="$ctrl.route.workerFk"
|
|
||||||
show-field="nickname"
|
|
||||||
vn-name="worker">
|
|
||||||
</vn-worker-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Vehicle"
|
|
||||||
ng-model="$ctrl.route.vehicleFk"
|
|
||||||
data="$ctrl.vehicles"
|
|
||||||
show-field="numberPlate"
|
|
||||||
value-field="id"
|
|
||||||
order="false"
|
|
||||||
vn-name="vehicle">
|
|
||||||
<tpl-item>{{::numberPlate}} - {{::name}}</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
label="Created"
|
|
||||||
ng-model="$ctrl.route.created"
|
|
||||||
vn-name="created">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-autocomplete
|
|
||||||
ng-model="$ctrl.route.agencyModeFk"
|
|
||||||
url="AgencyModes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Agency"
|
|
||||||
vn-name="agencyMode">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
label="Km start"
|
|
||||||
ng-model="$ctrl.route.kmStart"
|
|
||||||
vn-name="kmStart"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
label="Km end"
|
|
||||||
ng-model="$ctrl.route.kmEnd"
|
|
||||||
vn-name="kmEnd"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-time
|
|
||||||
label="Hour started"
|
|
||||||
ng-model="$ctrl.route.started"
|
|
||||||
vn-name="started">
|
|
||||||
</vn-input-time>
|
|
||||||
<vn-input-time
|
|
||||||
label="Hour finished"
|
|
||||||
ng-model="$ctrl.route.finished"
|
|
||||||
vn-name="finished">
|
|
||||||
</vn-input-time>
|
|
||||||
<vn-check
|
|
||||||
class="vn-mr-md"
|
|
||||||
label="Is served"
|
|
||||||
ng-model="$ctrl.route.isOk"
|
|
||||||
vn-name="isOk">
|
|
||||||
</vn-check>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textArea
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.route.description"
|
|
||||||
vn-name="description"
|
|
||||||
rule
|
|
||||||
vn-focus>
|
|
||||||
</vn-textArea>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,28 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
$onInit() {
|
|
||||||
this.$http.post(`Vehicles/sorted`, {warehouseFk: this.vnConfig.warehouseFk})
|
|
||||||
.then(res => {
|
|
||||||
this.vehicles = res.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.submit().then(() =>
|
|
||||||
this.card.reload()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteBasicData', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
route: '<'
|
|
||||||
},
|
|
||||||
require: {
|
|
||||||
card: '^vnRouteCard'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,8 +0,0 @@
|
||||||
Date finished: Fecha fin
|
|
||||||
Date started: Fecha inicio
|
|
||||||
Km start: Km de inicio
|
|
||||||
Km end: Km de fin
|
|
||||||
Description: Descripción
|
|
||||||
Hour started: Hora inicio
|
|
||||||
Hour finished: Hora fin
|
|
||||||
Is served: Se ha servido
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-route-descriptor route="$ctrl.route" card-reload="$ctrl.reload()"></vn-route-descriptor>
|
|
||||||
<vn-left-menu source="card"></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -1,71 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import ModuleCard from 'salix/components/module-card';
|
|
||||||
|
|
||||||
class Controller extends ModuleCard {
|
|
||||||
reload() {
|
|
||||||
let filter = {
|
|
||||||
fields: [
|
|
||||||
'id',
|
|
||||||
'workerFk',
|
|
||||||
'agencyModeFk',
|
|
||||||
'created',
|
|
||||||
'm3',
|
|
||||||
'warehouseFk',
|
|
||||||
'description',
|
|
||||||
'vehicleFk',
|
|
||||||
'kmStart',
|
|
||||||
'kmEnd',
|
|
||||||
'started',
|
|
||||||
'finished',
|
|
||||||
'cost',
|
|
||||||
'zoneFk',
|
|
||||||
'isOk'
|
|
||||||
],
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'agencyMode',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'name']
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'vehicle',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'm3']
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'zone',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'name']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'worker',
|
|
||||||
scope: {
|
|
||||||
fields: ['id'],
|
|
||||||
include: {
|
|
||||||
relation: 'user',
|
|
||||||
scope: {
|
|
||||||
fields: ['id'],
|
|
||||||
include: {
|
|
||||||
relation: 'emailUser',
|
|
||||||
scope: {
|
|
||||||
fields: ['email']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http.get(`Routes/${this.$params.id}`, {filter})
|
|
||||||
.then(res => this.route = res.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteCard', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="Routes"
|
|
||||||
data="$ctrl.route"
|
|
||||||
insert-mode="true"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-worker-autocomplete
|
|
||||||
ng-model="$ctrl.route.workerFk"
|
|
||||||
show-field="nickname">
|
|
||||||
</vn-worker-autocomplete>
|
|
||||||
<vn-date-picker
|
|
||||||
label="Created"
|
|
||||||
ng-model="$ctrl.route.created">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Vehicle"
|
|
||||||
ng-model="$ctrl.route.vehicleFk"
|
|
||||||
url="Vehicles"
|
|
||||||
show-field="numberPlate">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Agency"
|
|
||||||
ng-model="$ctrl.route.agencyModeFk"
|
|
||||||
url="AgencyModes">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.route.description"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Create">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="route.index">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,20 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.submit().then(
|
|
||||||
res => {
|
|
||||||
this.$http.post(`Routes/${res.data.id}/updateWorkCenter`, null)
|
|
||||||
.then(() => {
|
|
||||||
this.$state.go('route.card.summary', {id: res.data.id});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteCreate', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,11 +0,0 @@
|
||||||
<slot-descriptor>
|
|
||||||
<vn-route-descriptor>
|
|
||||||
<btn-three>
|
|
||||||
<vn-quick-link
|
|
||||||
tooltip="Route summary"
|
|
||||||
state="['route.card.summary', {id: $ctrl.id}]"
|
|
||||||
icon="icon-delivery">
|
|
||||||
</vn-quick-link>
|
|
||||||
</btn-three>
|
|
||||||
</vn-route-descriptor>
|
|
||||||
</slot-descriptor>
|
|
|
@ -1,9 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import DescriptorPopover from 'salix/components/descriptor-popover';
|
|
||||||
|
|
||||||
class Controller extends DescriptorPopover {}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteDescriptorPopover', {
|
|
||||||
slotTemplate: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,75 +0,0 @@
|
||||||
<vn-descriptor-content
|
|
||||||
module="route"
|
|
||||||
description="$ctrl.route.name"
|
|
||||||
summary="$ctrl.$.summary">
|
|
||||||
<slot-menu>
|
|
||||||
<vn-item
|
|
||||||
ng-click="$ctrl.showRouteReport()"
|
|
||||||
translate>
|
|
||||||
Show route report
|
|
||||||
</vn-item>
|
|
||||||
<vn-item
|
|
||||||
ng-click="$ctrl.sendRouteReport()"
|
|
||||||
translate>
|
|
||||||
Send route report
|
|
||||||
</vn-item>
|
|
||||||
<vn-item
|
|
||||||
ng-click="updateVolumeConfirmation.show()"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
vn-acl-action="remove"
|
|
||||||
translate>
|
|
||||||
Update volume
|
|
||||||
</vn-item>
|
|
||||||
<vn-item
|
|
||||||
ng-click="$ctrl.deleteCurrentRoute()"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
vn-acl-action="remove"
|
|
||||||
translate>
|
|
||||||
Delete route
|
|
||||||
</vn-item>
|
|
||||||
</slot-menu>
|
|
||||||
<slot-body>
|
|
||||||
<div class="attributes">
|
|
||||||
<vn-label-value
|
|
||||||
label="Date"
|
|
||||||
value="{{$ctrl.route.created | date: 'dd/MM/yyyy'}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Agency"
|
|
||||||
value="{{$ctrl.route.agencyMode.name}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Zone"
|
|
||||||
value="{{$ctrl.route.zone.name}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Volume"
|
|
||||||
value="{{$ctrl.route.m3 | dashIfEmpty}} / {{$ctrl.route.vehicle.m3 | dashIfEmpty}} m³">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Description"
|
|
||||||
value="{{$ctrl.route.description}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</div>
|
|
||||||
<div class="icons">
|
|
||||||
<vn-icon
|
|
||||||
vn-tooltip="Volume exceded"
|
|
||||||
icon="icon-volume"
|
|
||||||
ng-if="$ctrl.route.m3 > $ctrl.route.vehicle.m3 && $ctrl.route.vehicle.m3 != NULL">
|
|
||||||
</vn-icon>
|
|
||||||
</div>
|
|
||||||
<div class="quicklinks">
|
|
||||||
<div ng-transclude="btnOne"></div>
|
|
||||||
<div ng-transclude="btnTwo"></div>
|
|
||||||
<div ng-transclude="btnThree"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="updateVolumeConfirmation"
|
|
||||||
on-accept="$ctrl.updateVolume()"
|
|
||||||
question="Are you sure you want to update the volume?">
|
|
||||||
</vn-confirm>
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-route-summary route="$ctrl.route"></vn-route-summary>
|
|
||||||
</vn-popup>
|
|
|
@ -1,112 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Descriptor from 'salix/components/descriptor';
|
|
||||||
|
|
||||||
class Controller extends Descriptor {
|
|
||||||
get route() {
|
|
||||||
return this.entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
set route(value) {
|
|
||||||
this.entity = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
showRouteReport() {
|
|
||||||
this.vnReport.show(`Routes/${this.id}/driver-route-pdf`, {
|
|
||||||
id: this.id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
sendRouteReport() {
|
|
||||||
const workerUser = this.route.worker.user;
|
|
||||||
this.vnEmail.send(`Routes/${this.id}/driver-route-email`, {
|
|
||||||
recipient: workerUser.emailUser.email,
|
|
||||||
id: this.id
|
|
||||||
});
|
|
||||||
const params = {isOk: true};
|
|
||||||
return this.$http.patch(`Routes/${this.id}`, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateVolume() {
|
|
||||||
this.$http.post(`Routes/${this.id}/updateVolume`)
|
|
||||||
.then(() => {
|
|
||||||
if (this.cardReload) this.cardReload();
|
|
||||||
this.vnApp.showSuccess(this.$t('Volume updated'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteCurrentRoute() {
|
|
||||||
this.$http.delete(`Routes/${this.id}`)
|
|
||||||
.then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Route deleted'));
|
|
||||||
this.$state.go('route.index');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
loadData() {
|
|
||||||
const filter = {
|
|
||||||
fields: [
|
|
||||||
'id',
|
|
||||||
'workerFk',
|
|
||||||
'agencyModeFk',
|
|
||||||
'created',
|
|
||||||
'm3',
|
|
||||||
'warehouseFk',
|
|
||||||
'description',
|
|
||||||
'vehicleFk',
|
|
||||||
'kmStart',
|
|
||||||
'kmEnd',
|
|
||||||
'started',
|
|
||||||
'finished',
|
|
||||||
'cost',
|
|
||||||
'zoneFk'
|
|
||||||
],
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'agencyMode',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'name']
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'vehicle',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'm3']
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'zone',
|
|
||||||
scope: {
|
|
||||||
fields: ['id', 'name']
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'worker',
|
|
||||||
scope: {
|
|
||||||
fields: ['id'],
|
|
||||||
include: {
|
|
||||||
relation: 'user',
|
|
||||||
scope: {
|
|
||||||
fields: ['id'],
|
|
||||||
include: {
|
|
||||||
relation: 'emailUser',
|
|
||||||
scope: {
|
|
||||||
fields: ['email']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.getData(`Routes/${this.id}`, {filter})
|
|
||||||
.then(res => this.entity = res.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteDescriptor', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
route: '<',
|
|
||||||
cardReload: '&?'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,42 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('vnRouteDescriptorPopover', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
controller = $componentController('vnRouteDescriptor', {$element: null});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('loadData()', () => {
|
|
||||||
it(`should perform a get query to store the client data into the controller`, () => {
|
|
||||||
const id = 1;
|
|
||||||
const response = 'foo';
|
|
||||||
|
|
||||||
$httpBackend.expectRoute('GET', `Routes/${id}`).respond(response);
|
|
||||||
controller.id = id;
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.route).toEqual(response);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('deleteCurrentRoute()', () => {
|
|
||||||
it(`should perform a delete query to delete the current route`, () => {
|
|
||||||
const id = 1;
|
|
||||||
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
|
|
||||||
controller._id = id;
|
|
||||||
$httpBackend.expectDELETE(`Routes/${id}`).respond(200);
|
|
||||||
controller.deleteCurrentRoute();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.route).toBeUndefined();
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Route deleted');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,9 +0,0 @@
|
||||||
Volume exceded: Volumen excedido
|
|
||||||
Volume: Volumen
|
|
||||||
Send route report: Enviar informe de ruta
|
|
||||||
Show route report: Ver informe de ruta
|
|
||||||
Update volume: Actualizar volumen
|
|
||||||
Volume updated: Volumen actualizado
|
|
||||||
Delete route: Borrar ruta
|
|
||||||
Route deleted: Ruta borrada
|
|
||||||
Are you sure you want to update the volume?: Estas seguro que quieres actualizar el volumen?
|
|
|
@ -1,19 +1,3 @@
|
||||||
export * from './module';
|
export * from './module';
|
||||||
|
|
||||||
import './main';
|
import './main';
|
||||||
import './index/';
|
|
||||||
import './search-panel';
|
|
||||||
import './descriptor';
|
|
||||||
import './descriptor-popover';
|
|
||||||
import './summary';
|
|
||||||
import './card';
|
|
||||||
import './create';
|
|
||||||
import './basic-data';
|
|
||||||
import './log';
|
|
||||||
import './tickets';
|
|
||||||
import './agency-term/index';
|
|
||||||
import './agency-term/createInvoiceIn';
|
|
||||||
import './agency-term-search-panel';
|
|
||||||
import './ticket-popup';
|
|
||||||
import './sms';
|
|
||||||
import './roadmap';
|
|
||||||
|
|
|
@ -1,228 +0,0 @@
|
||||||
<vn-auto-search
|
|
||||||
model="model">
|
|
||||||
</vn-auto-search>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="AgencyModes"
|
|
||||||
data="agencyModes">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Vehicles"
|
|
||||||
data="vehicles">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Workers/activeWithInheritedRole"
|
|
||||||
data="activeWithInheritedRole">
|
|
||||||
</vn-crud-model>
|
|
||||||
<div class="vn-w-xl">
|
|
||||||
<vn-card>
|
|
||||||
<smart-table
|
|
||||||
model="model"
|
|
||||||
options="$ctrl.smartTableOptions"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
|
||||||
<slot-actions>
|
|
||||||
<section class="header">
|
|
||||||
<vn-tool-bar class="vn-mb-md">
|
|
||||||
<vn-button
|
|
||||||
icon="icon-clone"
|
|
||||||
ng-show="$ctrl.totalChecked > 0"
|
|
||||||
ng-click="$ctrl.openClonationDialog()"
|
|
||||||
vn-tooltip="Clone selected routes">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
icon="cloud_download"
|
|
||||||
ng-show="$ctrl.totalChecked > 0"
|
|
||||||
ng-click="$ctrl.showRouteReport()"
|
|
||||||
vn-tooltip="Download selected routes as PDF">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
icon="check"
|
|
||||||
ng-show="$ctrl.totalChecked > 0"
|
|
||||||
ng-click="$ctrl.markAsServed()"
|
|
||||||
vn-tooltip="Mark as served">
|
|
||||||
</vn-button>
|
|
||||||
</section>
|
|
||||||
</slot-actions>
|
|
||||||
<slot-table>
|
|
||||||
<table model="model">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th shrink>
|
|
||||||
<vn-multi-check
|
|
||||||
model="model">
|
|
||||||
</vn-multi-check>
|
|
||||||
</th>
|
|
||||||
<th field="id" number>
|
|
||||||
<span translate>Id</span>
|
|
||||||
</th>
|
|
||||||
<th field="workerFk">
|
|
||||||
<span translate>Worker</span>
|
|
||||||
</th>
|
|
||||||
<th field="agencyName">
|
|
||||||
<span translate>Agency</span>
|
|
||||||
</th>
|
|
||||||
<th field="vehiclePlateNumber">
|
|
||||||
<span translate>Vehicle</span>
|
|
||||||
</th>
|
|
||||||
<th field="created" shrink-date>
|
|
||||||
<span translate>Date</span>
|
|
||||||
</th>
|
|
||||||
<th field="m3" number>
|
|
||||||
<span translate>m³</span>
|
|
||||||
</th>
|
|
||||||
<th field="description">
|
|
||||||
<span translate>Description</span>
|
|
||||||
</th>
|
|
||||||
<th field="started">
|
|
||||||
<span translate>Hour started</span>
|
|
||||||
</th>
|
|
||||||
<th field="finished">
|
|
||||||
<span translate>Hour finished</span>
|
|
||||||
</th>
|
|
||||||
<th shrink></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="route in model.data"
|
|
||||||
class="clickable vn-tr search-result"
|
|
||||||
ng-attr-id="{{::route.id}}" vn-droppable="$ctrl.onDrop($event)">
|
|
||||||
<td shrink>
|
|
||||||
<vn-check
|
|
||||||
ng-model="route.checked"
|
|
||||||
vn-click-stop>
|
|
||||||
</vn-check>
|
|
||||||
</td>
|
|
||||||
<td number>{{::route.id | dashIfEmpty}}</td>
|
|
||||||
<td>
|
|
||||||
<vn-autocomplete
|
|
||||||
ng-model="route.workerFk"
|
|
||||||
data="activeWithInheritedRole"
|
|
||||||
show-field="nickname"
|
|
||||||
search-function="{firstName: $search}"
|
|
||||||
value-field="id"
|
|
||||||
where="{role: 'employee'}"
|
|
||||||
on-change="$ctrl.updateAttributes(route)"
|
|
||||||
vn-click-stop>
|
|
||||||
<tpl-item>
|
|
||||||
<div>{{name}} - {{nickname}}</div>
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</td>
|
|
||||||
<td expand>
|
|
||||||
<vn-autocomplete
|
|
||||||
ng-model="route.agencyModeFk"
|
|
||||||
data="agencyModes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
on-change="$ctrl.updateAttributes(route)"
|
|
||||||
vn-click-stop>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</td>
|
|
||||||
<td expand>
|
|
||||||
<vn-autocomplete
|
|
||||||
ng-model="route.vehicleFk"
|
|
||||||
data="vehicles"
|
|
||||||
show-field="numberPlate"
|
|
||||||
value-field="id"
|
|
||||||
on-change="$ctrl.updateAttributes(route)"
|
|
||||||
vn-click-stop>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</td >
|
|
||||||
<td>
|
|
||||||
<vn-date-picker
|
|
||||||
ng-model="route.created"
|
|
||||||
on-change="$ctrl.updateAttributes(route)">
|
|
||||||
</vn-horizontal>
|
|
||||||
</td>
|
|
||||||
<td number>{{::route.m3 | dashIfEmpty}}</td>
|
|
||||||
<td>
|
|
||||||
<vn-textfield
|
|
||||||
ng-model="route.description"
|
|
||||||
on-change="$ctrl.updateAttributes(route)">
|
|
||||||
</vn-textfield>
|
|
||||||
</td>
|
|
||||||
<td expand>
|
|
||||||
<vn-input-time
|
|
||||||
ng-model="route.started"
|
|
||||||
on-change="$ctrl.updateAttributes(route)">
|
|
||||||
</vn-input-time>
|
|
||||||
</td>
|
|
||||||
<td expand>
|
|
||||||
<vn-input-time
|
|
||||||
ng-model="route.finished"
|
|
||||||
on-change="$ctrl.updateAttributes(route)">
|
|
||||||
</vn-input-time>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.showTicketPopup(route)"
|
|
||||||
vn-tooltip="Añadir tickets"
|
|
||||||
icon="icon-ticketAdd">
|
|
||||||
</vn-icon-button>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(route)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</slot-table>
|
|
||||||
</smart-table>
|
|
||||||
</vn-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-route-summary
|
|
||||||
route="$ctrl.routeSelected">
|
|
||||||
</vn-route-summary>
|
|
||||||
</vn-popup>
|
|
||||||
|
|
||||||
<vn-route-ticket-popup
|
|
||||||
vn-id="ticketPopup"
|
|
||||||
route="$ctrl.routeSelected">
|
|
||||||
</vn-route-ticket-popup>
|
|
||||||
|
|
||||||
<vn-worker-descriptor-popover
|
|
||||||
vn-id="workerDescriptor">
|
|
||||||
</vn-worker-descriptor-popover>
|
|
||||||
<vn-ticket-descriptor-popover
|
|
||||||
vn-id="ticketDescriptor">
|
|
||||||
</vn-ticket-descriptor-popover>
|
|
||||||
<vn-client-descriptor-popover
|
|
||||||
vn-id="clientDescriptor">
|
|
||||||
</vn-client-descriptor-popover>
|
|
||||||
|
|
||||||
<div fixed-bottom-right>
|
|
||||||
<vn-vertical style="align-items: center;">
|
|
||||||
<a ui-sref="route.create" vn-bind="+">
|
|
||||||
<vn-button class="round md vn-mb-sm"
|
|
||||||
icon="add"
|
|
||||||
vn-tooltip="New route"
|
|
||||||
tooltip-position="left">
|
|
||||||
</vn-button>
|
|
||||||
</a>
|
|
||||||
</vn-vertical>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Clonation dialog -->
|
|
||||||
<vn-dialog class="edit"
|
|
||||||
vn-id="clonationDialog"
|
|
||||||
on-accept="$ctrl.cloneSelectedRoutes()"
|
|
||||||
message="Select the starting date">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
label="Starting date"
|
|
||||||
ng-model="$ctrl.createdDate">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Clone</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
|
@ -1,151 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
constructor($element, $, vnReport) {
|
|
||||||
super($element, $);
|
|
||||||
this.vnReport = vnReport;
|
|
||||||
this.droppableElement = 'a.vn-tr';
|
|
||||||
}
|
|
||||||
|
|
||||||
preview(route) {
|
|
||||||
this.routeSelected = route;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
showTicketPopup(route) {
|
|
||||||
this.routeSelected = route;
|
|
||||||
this.$.ticketPopup.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
get checked() {
|
|
||||||
const rows = this.$.model.data || [];
|
|
||||||
const checkedRows = [];
|
|
||||||
for (let row of rows) {
|
|
||||||
if (row.checked)
|
|
||||||
checkedRows.push(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkedRows;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalChecked() {
|
|
||||||
return this.checked.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
showRouteReport() {
|
|
||||||
const routesIds = [];
|
|
||||||
const access_token = this.vnToken.tokenMultimedia;
|
|
||||||
|
|
||||||
for (let route of this.checked)
|
|
||||||
routesIds.push(route.id);
|
|
||||||
const stringRoutesIds = routesIds.join(',');
|
|
||||||
|
|
||||||
if (this.checked.length <= 1) {
|
|
||||||
const url = `api/Routes/${stringRoutesIds}/driver-route-pdf?access_token=${access_token}`;
|
|
||||||
window.open(url, '_blank');
|
|
||||||
} else {
|
|
||||||
const serializedParams = this.$httpParamSerializer({
|
|
||||||
access_token,
|
|
||||||
id: stringRoutesIds
|
|
||||||
});
|
|
||||||
const url = `api/Routes/downloadZip?${serializedParams}`;
|
|
||||||
window.open(url, '_blank');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
openClonationDialog() {
|
|
||||||
this.$.clonationDialog.show();
|
|
||||||
this.createdDate = Date.vnNew();
|
|
||||||
}
|
|
||||||
|
|
||||||
cloneSelectedRoutes() {
|
|
||||||
try {
|
|
||||||
if (!this.createdDate)
|
|
||||||
throw new Error(`The date can't be empty`);
|
|
||||||
|
|
||||||
const routesIds = [];
|
|
||||||
for (let route of this.checked)
|
|
||||||
routesIds.push(route.id);
|
|
||||||
|
|
||||||
return this.$http.post('Routes/clone', {ids: routesIds, created: this.createdDate}).then(() => {
|
|
||||||
this.$.model.refresh();
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.vnApp.showError(this.$t(e.message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onDrop($event) {
|
|
||||||
const target = $event.target;
|
|
||||||
const droppable = target.closest(this.droppableElement);
|
|
||||||
const ticketId = $event.dataTransfer.getData('Text');
|
|
||||||
const routeId = droppable.id;
|
|
||||||
|
|
||||||
if (isNaN(ticketId)) {
|
|
||||||
const regexp = new RegExp(/\/ticket\/([0-9]+)\//i);
|
|
||||||
const matches = ticketId.match(regexp);
|
|
||||||
|
|
||||||
if (matches && matches.length)
|
|
||||||
this.insert(routeId, matches[1]);
|
|
||||||
else
|
|
||||||
this.vnApp.showError(this.$t('Ticket not found'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isNaN(ticketId))
|
|
||||||
this.insert(routeId, ticketId);
|
|
||||||
}
|
|
||||||
|
|
||||||
insert(routeId, ticketId) {
|
|
||||||
routeId = parseInt(routeId);
|
|
||||||
ticketId = parseInt(ticketId);
|
|
||||||
|
|
||||||
const query = `Routes/${routeId}/insertTicket`;
|
|
||||||
return this.$http.patch(query, {ticketId}).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
this.$.model.refresh();
|
|
||||||
}).catch(error => {
|
|
||||||
if (error.status == 404)
|
|
||||||
return this.vnApp.showError(this.$t('Ticket not found'));
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
updateAttributes(route) {
|
|
||||||
if (route.started == null || route.finished == null)
|
|
||||||
return this.vnApp.showError(this.$t('You must select a valid time'));
|
|
||||||
if (route.created == null)
|
|
||||||
return this.vnApp.showError(this.$t('You must select a valid date'));
|
|
||||||
const params = {
|
|
||||||
workerFk: route.workerFk,
|
|
||||||
agencyModeFk: route.agencyModeFk,
|
|
||||||
vehicleFk: route.vehicleFk,
|
|
||||||
created: route.created,
|
|
||||||
description: route.description,
|
|
||||||
started: route.started,
|
|
||||||
finished: route.finished
|
|
||||||
};
|
|
||||||
const query = `Routes/${route.id}/`;
|
|
||||||
this.$http.patch(query, params).then(res => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
markAsServed() {
|
|
||||||
const routes = [];
|
|
||||||
for (let route of this.checked)
|
|
||||||
routes.push(route.id);
|
|
||||||
|
|
||||||
const params = {isOk: true};
|
|
||||||
for (let routeId of routes)
|
|
||||||
this.$http.patch(`Routes/${routeId}`, params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope', 'vnReport'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,156 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
import crudModel from 'core/mocks/crud-model';
|
|
||||||
|
|
||||||
describe('Component vnRouteIndex', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
const $element = angular.element('<vn-route-index></vn-route-index>');
|
|
||||||
controller = $componentController('vnRouteIndex', {$element});
|
|
||||||
controller.$.model = crudModel;
|
|
||||||
controller.$.model.data = [{id: 1, checked: true}, {id: 2}, {id: 3}];
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('checked() getter', () => {
|
|
||||||
it('should return the checked lines', () => {
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
data[2].checked = true;
|
|
||||||
|
|
||||||
const checkedRows = controller.checked;
|
|
||||||
|
|
||||||
const firstCheckedRow = checkedRows[0];
|
|
||||||
const secondCheckedRow = checkedRows[1];
|
|
||||||
|
|
||||||
expect(firstCheckedRow.id).toEqual(1);
|
|
||||||
expect(secondCheckedRow.id).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('totalCheked() getter', () => {
|
|
||||||
it('should return the total checked lines', () => {
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
|
|
||||||
const checkedRows = controller.totalChecked;
|
|
||||||
|
|
||||||
expect(checkedRows).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('showRouteReport()', () => {
|
|
||||||
it('should call to the vnReport show method', () => {
|
|
||||||
jest.spyOn(window, 'open').mockReturnThis();
|
|
||||||
|
|
||||||
const data = controller.$.model.data;
|
|
||||||
data[0].checked = true;
|
|
||||||
data[2].checked = true;
|
|
||||||
|
|
||||||
controller.showRouteReport();
|
|
||||||
|
|
||||||
expect(window.open).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('cloneSelectedRoutes()', () => {
|
|
||||||
it('should perform an http request to Routes/clone', () => {
|
|
||||||
controller.createdDate = Date.vnNew();
|
|
||||||
|
|
||||||
$httpBackend.expect('POST', 'Routes/clone').respond();
|
|
||||||
controller.cloneSelectedRoutes();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onDrop()', () => {
|
|
||||||
it('should call the insert method when dragging a ticket number', () => {
|
|
||||||
jest.spyOn(controller, 'insert');
|
|
||||||
|
|
||||||
const routeId = '1';
|
|
||||||
const expectedTicketId = '16';
|
|
||||||
const draggedElement = '16';
|
|
||||||
const droppable = document.createElement('a');
|
|
||||||
droppable.setAttribute('id', 1);
|
|
||||||
droppable.classList.add('vn-tr');
|
|
||||||
|
|
||||||
const $event = {
|
|
||||||
dataTransfer: {
|
|
||||||
getData: () => draggedElement
|
|
||||||
},
|
|
||||||
target: droppable
|
|
||||||
};
|
|
||||||
controller.onDrop($event);
|
|
||||||
|
|
||||||
expect(controller.insert).toHaveBeenCalledWith(routeId, expectedTicketId);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the insert method when dragging a ticket link', () => {
|
|
||||||
jest.spyOn(controller, 'insert');
|
|
||||||
|
|
||||||
const routeId = '1';
|
|
||||||
const expectedTicketId = '11';
|
|
||||||
const draggedElement = 'http://arkamcity.com/#!/ticket/11/summary';
|
|
||||||
const droppable = document.createElement('a');
|
|
||||||
droppable.setAttribute('id', 1);
|
|
||||||
droppable.classList.add('vn-tr');
|
|
||||||
|
|
||||||
const $event = {
|
|
||||||
dataTransfer: {
|
|
||||||
getData: () => draggedElement
|
|
||||||
},
|
|
||||||
target: droppable
|
|
||||||
};
|
|
||||||
controller.onDrop($event);
|
|
||||||
|
|
||||||
expect(controller.insert).toHaveBeenCalledWith(routeId, expectedTicketId);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error when dragging an invalid ticket link', () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showError');
|
|
||||||
|
|
||||||
const draggedElement = 'http://arkamcity.com/#!/item/11/summary';
|
|
||||||
const droppable = document.createElement('a');
|
|
||||||
droppable.setAttribute('id', 1);
|
|
||||||
droppable.classList.add('vn-tr');
|
|
||||||
const $event = {
|
|
||||||
dataTransfer: {
|
|
||||||
getData: () => draggedElement
|
|
||||||
},
|
|
||||||
target: droppable
|
|
||||||
};
|
|
||||||
controller.onDrop($event);
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith('Ticket not found');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('insert()', () => {
|
|
||||||
it('should perform a HTTP patch query and then call both refresh and showSuccess methods', () => {
|
|
||||||
jest.spyOn(controller.$.model, 'refresh').mockReturnThis();
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
|
|
||||||
const routeId = 1;
|
|
||||||
const ticketId = 11;
|
|
||||||
const data = {ticketId};
|
|
||||||
$httpBackend.expect('PATCH', `Routes/1/insertTicket`, data).respond();
|
|
||||||
controller.insert(routeId, ticketId);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('markAsServed()', () => {
|
|
||||||
it('should perform a HTTP patch query', () => {
|
|
||||||
const data = {isOk: true};
|
|
||||||
$httpBackend.expect('PATCH', `Routes/1`, data).respond();
|
|
||||||
controller.markAsServed();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,13 +0,0 @@
|
||||||
Vehicle: Vehículo
|
|
||||||
Download selected routes as PDF: Descargar rutas seleccionadas como PDF
|
|
||||||
Clone selected routes: Clonar rutas seleccionadas
|
|
||||||
The date can't be empty: La fecha no puede estar vacía
|
|
||||||
Starting date: Fecha de inicio
|
|
||||||
Hour started: Hora inicio
|
|
||||||
Hour finished: Hora fin
|
|
||||||
Go to route: Ir a la ruta
|
|
||||||
You must select a valid time: Debe seleccionar una hora válida
|
|
||||||
You must select a valid date: Debe seleccionar una fecha válida
|
|
||||||
Mark as served: Marcar como servidas
|
|
||||||
Retrieving data from the routes: Recuperando datos de las rutas
|
|
||||||
Send SMS to all clients: Mandar sms a todos los clientes de las rutas
|
|
|
@ -1 +0,0 @@
|
||||||
Unlink zone: Unlink zone {{zoneName}} from agency {{agencyName}}
|
|
|
@ -1,5 +0,0 @@
|
||||||
Routes: Rutas
|
|
||||||
Search routes by id: Buscar rutas por identificador
|
|
||||||
New route: Nueva ruta
|
|
||||||
route: ruta
|
|
||||||
Unlink zone: Desvincular zona {{zoneName}} de agencia {{agencyName}}
|
|
|
@ -1 +0,0 @@
|
||||||
<vn-log url="RouteLogs" origin-id="$ctrl.$params.id"></vn-log>
|
|
|
@ -1,7 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteLog', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Section,
|
|
||||||
});
|
|
|
@ -1,20 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="Routes/filter"
|
|
||||||
limit="20"
|
|
||||||
order="created DESC, id DESC">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
vn-focus
|
|
||||||
panel="vn-route-search-panel"
|
|
||||||
info="Search routes by id"
|
|
||||||
fetch-params="$ctrl.fetchParams($params)"
|
|
||||||
filter="$ctrl.filterParams"
|
|
||||||
model="model">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-left-menu></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -2,40 +2,16 @@ import ngModule from '../module';
|
||||||
import ModuleMain from 'salix/components/module-main';
|
import ModuleMain from 'salix/components/module-main';
|
||||||
|
|
||||||
export default class Route extends ModuleMain {
|
export default class Route extends ModuleMain {
|
||||||
$postLink() {
|
constructor($element, $) {
|
||||||
const to = Date.vnNew();
|
super($element, $);
|
||||||
to.setDate(to.getDate() + 1);
|
|
||||||
to.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const from = Date.vnNew();
|
|
||||||
from.setDate(from.getDate());
|
|
||||||
from.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
this.filterParams = {from, to};
|
|
||||||
this.$.model.applyFilter(null, this.filterParams);
|
|
||||||
}
|
}
|
||||||
|
async $onInit() {
|
||||||
fetchParams($params) {
|
this.$state.go('home');
|
||||||
const hasEntries = Object.entries($params).length;
|
window.location.href = await this.vnApp.getUrl(`route/`);
|
||||||
if (!hasEntries)
|
|
||||||
$params.scopeDays = 1;
|
|
||||||
|
|
||||||
if (typeof $params.scopeDays === 'number') {
|
|
||||||
const from = Date.vnNew();
|
|
||||||
from.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const to = new Date(from.getTime());
|
|
||||||
to.setDate(to.getDate() + $params.scopeDays);
|
|
||||||
to.setHours(23, 59, 59, 999);
|
|
||||||
|
|
||||||
Object.assign($params, {from, to});
|
|
||||||
}
|
|
||||||
|
|
||||||
return $params;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngModule.vnComponent('vnRoute', {
|
ngModule.vnComponent('vnRoute', {
|
||||||
controller: Route,
|
controller: Entry,
|
||||||
template: require('./index.html')
|
template: require('./index.html')
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Route Component vnRoute', () => {
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject($componentController => {
|
|
||||||
let $element = angular.element(`<div></div>`);
|
|
||||||
controller = $componentController('vnRoute', {$element});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('fetchParams()', () => {
|
|
||||||
it('should return a range of dates with passed scope days', () => {
|
|
||||||
let params = controller.fetchParams({
|
|
||||||
scopeDays: 2
|
|
||||||
});
|
|
||||||
const from = Date.vnNew();
|
|
||||||
from.setHours(0, 0, 0, 0);
|
|
||||||
const to = new Date(from.getTime());
|
|
||||||
to.setDate(to.getDate() + params.scopeDays);
|
|
||||||
to.setHours(23, 59, 59, 999);
|
|
||||||
|
|
||||||
const expectedParams = {
|
|
||||||
from,
|
|
||||||
scopeDays: params.scopeDays,
|
|
||||||
to
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(params).toEqual(expectedParams);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return default value for scope days', () => {
|
|
||||||
let params = controller.fetchParams({
|
|
||||||
scopeDays: 1
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(params.scopeDays).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the given scope days', () => {
|
|
||||||
let params = controller.fetchParams({
|
|
||||||
scopeDays: 2
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(params.scopeDays).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -0,0 +1 @@
|
||||||
|
route: route
|
|
@ -1,98 +0,0 @@
|
||||||
<mg-ajax path="Roadmaps/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.roadmap"
|
|
||||||
form="form"
|
|
||||||
save="patch">
|
|
||||||
</vn-watcher>
|
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield vn-focus
|
|
||||||
vn-one
|
|
||||||
label="Roadmap"
|
|
||||||
ng-model="$ctrl.roadmap.name"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="ETD date"
|
|
||||||
ng-model="$ctrl.roadmap.etd">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-input-time
|
|
||||||
vn-one
|
|
||||||
label="ETD hour"
|
|
||||||
ng-model="$ctrl.roadmap.etd">
|
|
||||||
</vn-input-time>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Tractor plate"
|
|
||||||
ng-model="$ctrl.roadmap.tractorPlate"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Trailer plate"
|
|
||||||
ng-model="$ctrl.roadmap.trailerPlate"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="$ctrl.roadmap.supplierFk"
|
|
||||||
url="Suppliers"
|
|
||||||
show-field="nickname"
|
|
||||||
search-function="{or: [{id: $search}, {nickname: {like: '%'+ $search +'%'}}]}"
|
|
||||||
value-field="id"
|
|
||||||
order="nickname"
|
|
||||||
label="Carrier">
|
|
||||||
<tpl-item>
|
|
||||||
{{::id}} - {{::nickname}}
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
label="Price"
|
|
||||||
ng-model="$ctrl.roadmap.price"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Driver name"
|
|
||||||
ng-model="$ctrl.roadmap.driverName"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Phone"
|
|
||||||
ng-model="$ctrl.roadmap.phone"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textArea
|
|
||||||
vn-one
|
|
||||||
label="Observations"
|
|
||||||
ng-model="$ctrl.roadmap.observations"
|
|
||||||
rule>
|
|
||||||
</vn-textArea>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,16 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.submit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnRoadmapBasicData', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
roadmap: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-roadmap-descriptor roadmap="$ctrl.roadmap"></vn-roadmap-descriptor>
|
|
||||||
<vn-left-menu source="roadmap"></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -1,19 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import ModuleCard from 'salix/components/module-card';
|
|
||||||
|
|
||||||
class Controller extends ModuleCard {
|
|
||||||
reload() {
|
|
||||||
const filter = {
|
|
||||||
include: [
|
|
||||||
{relation: 'supplier'}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
this.$http.get(`Roadmaps/${this.$params.id}`, {filter})
|
|
||||||
.then(res => this.roadmap = res.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRoadmapCard', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,37 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="Roadmaps"
|
|
||||||
data="$ctrl.roadmap"
|
|
||||||
insert-mode="true"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
label="Roadmap"
|
|
||||||
ng-model="$ctrl.roadmap.name"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-date-picker
|
|
||||||
label="ETD date"
|
|
||||||
ng-model="$ctrl.roadmap.etd">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-input-time
|
|
||||||
label="ETD hour"
|
|
||||||
ng-model="$ctrl.roadmap.etd">
|
|
||||||
</vn-input-time>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Create">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="roadmap.index">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,23 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
constructor($element, $, $transclude, vnReport, vnEmail) {
|
|
||||||
super($element, $, $transclude);
|
|
||||||
this.roadmap = {etd: Date.vnNew()};
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.submit().then(
|
|
||||||
res => this.$state.go('route.roadmap.card.summary', {id: res.data.id})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRoadmapCreate', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,6 +0,0 @@
|
||||||
vn-ticket-request {
|
|
||||||
.vn-textfield {
|
|
||||||
margin: 0!important;
|
|
||||||
max-width: 100px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
<vn-descriptor-content
|
|
||||||
module="route"
|
|
||||||
base-state="route.roadmap"
|
|
||||||
description="$ctrl.roadmap.name">
|
|
||||||
<slot-menu>
|
|
||||||
<vn-item
|
|
||||||
ng-click="deleteRoadmap.show()"
|
|
||||||
name="deleteRoadmap"
|
|
||||||
translate>
|
|
||||||
Delete roadmap
|
|
||||||
</vn-item>
|
|
||||||
</slot-menu>
|
|
||||||
<slot-body>
|
|
||||||
<div class="attributes">
|
|
||||||
<vn-label-value
|
|
||||||
label="Roadmap"
|
|
||||||
value="{{$ctrl.roadmap.name}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="ETD"
|
|
||||||
value="{{$ctrl.roadmap.etd | date:'dd/MM/yyyy HH:mm'}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Carrier">
|
|
||||||
<span ng-click="supplierDescriptor.show($event, $ctrl.roadmap.supplier.id)" class="link">
|
|
||||||
{{$ctrl.roadmap.supplier.nickname}}
|
|
||||||
</span>
|
|
||||||
</vn-label-value>
|
|
||||||
</div>
|
|
||||||
</slot-body>
|
|
||||||
</vn-descriptor-content>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="deleteRoadmap"
|
|
||||||
on-accept="$ctrl.onDelete()"
|
|
||||||
question="Are you sure you want to continue?"
|
|
||||||
message="The roadmap will be removed">
|
|
||||||
</vn-confirm>
|
|
||||||
<vn-supplier-descriptor-popover
|
|
||||||
vn-id="supplierDescriptor">
|
|
||||||
</vn-supplier-descriptor-popover>
|
|
|
@ -1,26 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Descriptor from 'salix/components/descriptor';
|
|
||||||
|
|
||||||
class Controller extends Descriptor {
|
|
||||||
get roadmap() {
|
|
||||||
return this.entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
set roadmap(value) {
|
|
||||||
this.entity = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
onDelete() {
|
|
||||||
return this.$http.delete(`Roadmaps/${this.roadmap.id}`)
|
|
||||||
.then(() => this.$state.go('route.roadmap'))
|
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('Roadmap removed')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnRoadmapDescriptor', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
roadmap: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
Delete roadmap: Eliminar troncal
|
|
||||||
The roadmap will be removed: La troncal será eliminada
|
|
||||||
Roadmap removed: Troncal eliminada
|
|
|
@ -1,9 +0,0 @@
|
||||||
import './main';
|
|
||||||
import './index/';
|
|
||||||
import './summary';
|
|
||||||
import './card';
|
|
||||||
import './descriptor';
|
|
||||||
import './create';
|
|
||||||
import './basic-data';
|
|
||||||
import './search-panel';
|
|
||||||
import './stops';
|
|
|
@ -1,112 +0,0 @@
|
||||||
<vn-auto-search
|
|
||||||
model="model">
|
|
||||||
</vn-auto-search>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="model"
|
|
||||||
class="vn-w-lg">
|
|
||||||
<vn-card class="vn-pa-md vn-w-lg">
|
|
||||||
<vn-tool-bar class="vn-ma-md">
|
|
||||||
<vn-button
|
|
||||||
disabled="$ctrl.totalChecked == 0"
|
|
||||||
ng-click="$ctrl.openClonationDialog()"
|
|
||||||
icon="icon-clone"
|
|
||||||
vn-tooltip="Clone selected roadmaps">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
disabled="$ctrl.totalChecked == 0"
|
|
||||||
ng-click="deleteRoadmaps.show()"
|
|
||||||
vn-tooltip="Delete roadmap(s)"
|
|
||||||
icon="delete">
|
|
||||||
</vn-button>
|
|
||||||
</vn-tool-bar>
|
|
||||||
<vn-table model="model">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th shrink>
|
|
||||||
<vn-multi-check
|
|
||||||
model="model">
|
|
||||||
</vn-multi-check>
|
|
||||||
</vn-th>
|
|
||||||
<vn-th field="description">Roadmap</vn-th>
|
|
||||||
<vn-th field="etd" expand date>ETD</vn-th>
|
|
||||||
<vn-th field="supplierFk">Carrier</vn-th>
|
|
||||||
<vn-th field="plate">Plate</vn-th>
|
|
||||||
<vn-th field="price">Price</vn-th>
|
|
||||||
<vn-th field="observations" expand>Observations</vn-th>
|
|
||||||
<vn-th></vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<a ng-repeat="roadmap in model.data"
|
|
||||||
class="clickable vn-tr search-result"
|
|
||||||
ui-sref="route.roadmap.card.summary({id: {{::roadmap.id}}})">
|
|
||||||
<vn-td>
|
|
||||||
<vn-check
|
|
||||||
ng-model="roadmap.checked"
|
|
||||||
vn-click-stop>
|
|
||||||
</vn-check>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>{{::roadmap.name}}</vn-td>
|
|
||||||
<vn-td expand date>{{::roadmap.etd | date:'dd/MM/yyyy HH:mm'}}</vn-td>
|
|
||||||
<vn-td expand>
|
|
||||||
<span
|
|
||||||
class="link"
|
|
||||||
vn-click-stop="supplierDescriptor.show($event, roadmap.supplierFk)">
|
|
||||||
{{::roadmap.supplier.nickname}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>{{::roadmap.tractorPlate | dashIfEmpty}}</vn-td>
|
|
||||||
<vn-td expand>{{::roadmap.price | currency: 'EUR':2 | dashIfEmpty}}</vn-td>
|
|
||||||
<vn-td expand>{{::roadmap.observations | dashIfEmpty}}</vn-td>
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(roadmap)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
</a>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<a
|
|
||||||
ui-sref="route.roadmap.create"
|
|
||||||
vn-tooltip="Create roadmap"
|
|
||||||
vn-bind="+"
|
|
||||||
fixed-bottom-right>
|
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
|
||||||
</a>
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-roadmap-summary
|
|
||||||
roadmap="$ctrl.roadmapSelected">
|
|
||||||
</vn-roadmap-summary>
|
|
||||||
</vn-popup>
|
|
||||||
<vn-supplier-descriptor-popover
|
|
||||||
vn-id="supplierDescriptor">
|
|
||||||
</vn-supplier-descriptor-popover>
|
|
||||||
|
|
||||||
<!-- Clonation dialog -->
|
|
||||||
<vn-dialog class="edit"
|
|
||||||
vn-id="clonationDialog"
|
|
||||||
on-accept="$ctrl.cloneSelectedRoadmaps()"
|
|
||||||
message="Select the estimated time of departure (ETD)">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
label="ETD"
|
|
||||||
ng-model="$ctrl.etd">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Clone</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="deleteRoadmaps"
|
|
||||||
question="Are you sure you want to continue?"
|
|
||||||
message="Selected roadmaps will be removed"
|
|
||||||
on-accept="$ctrl.deleteRoadmaps()">
|
|
||||||
</vn-confirm>
|
|
|
@ -1,60 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
get checked() {
|
|
||||||
const roadmaps = this.$.model.data || [];
|
|
||||||
const checkedRoadmap = [];
|
|
||||||
for (let roadmap of roadmaps) {
|
|
||||||
if (roadmap.checked)
|
|
||||||
checkedRoadmap.push(roadmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkedRoadmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
get totalChecked() {
|
|
||||||
return this.checked.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
preview(roadmap) {
|
|
||||||
this.roadmapSelected = roadmap;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
openClonationDialog() {
|
|
||||||
this.$.clonationDialog.show();
|
|
||||||
this.etd = Date.vnNew();
|
|
||||||
}
|
|
||||||
|
|
||||||
cloneSelectedRoadmaps() {
|
|
||||||
try {
|
|
||||||
if (!this.etd)
|
|
||||||
throw new Error(`The date can't be empty`);
|
|
||||||
|
|
||||||
const roadmapsIds = [];
|
|
||||||
for (let roadmap of this.checked)
|
|
||||||
roadmapsIds.push(roadmap.id);
|
|
||||||
|
|
||||||
return this.$http.post('Roadmaps/clone', {ids: roadmapsIds, etd: this.etd}).then(() => {
|
|
||||||
this.$.model.refresh();
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.vnApp.showError(this.$t(e.message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteRoadmaps() {
|
|
||||||
for (const roadmap of this.checked) {
|
|
||||||
this.$http.delete(`Roadmaps/${roadmap.id}`)
|
|
||||||
.then(() => this.$.model.refresh())
|
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('Roadmaps removed')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRoadmapIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
Delete roadmap(s): Eliminar troncal(es)
|
|
||||||
Selected roadmaps will be removed: Los troncales seleccionados serán eliminados
|
|
||||||
Roadmaps removed: Troncales eliminados
|
|
|
@ -1,14 +0,0 @@
|
||||||
Roadmaps: Troncales
|
|
||||||
Roadmap: Troncal
|
|
||||||
Driver name: Nombre conductor
|
|
||||||
Plate: Matrícula
|
|
||||||
Price: Precio
|
|
||||||
Observations: Observaciones
|
|
||||||
Clone selected roadmaps: Clonar troncales seleccionadas
|
|
||||||
Select the estimated time of departure (ETD): Seleccione la hora estimada de salida (ETD)
|
|
||||||
Create roadmap: Crear troncal
|
|
||||||
Tractor plate: Matrícula tractor
|
|
||||||
Trailer plate: Matrícula trailer
|
|
||||||
Carrier: Transportista
|
|
||||||
ETD date: Fecha ETD
|
|
||||||
ETD hour: Hora ETD
|
|
|
@ -1,20 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="Roadmaps"
|
|
||||||
include="$ctrl.include"
|
|
||||||
auto-load="true"
|
|
||||||
limit="20">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
info="Search roadmap by id or trunk"
|
|
||||||
panel="vn-roadmap-search-panel"
|
|
||||||
model="model"
|
|
||||||
filter="$ctrl.filterParams"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
|
||||||
base-state="route.roadmap">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view>
|
|
||||||
<vn-roadmap-index></vn-roadmap-index>
|
|
||||||
</ui-view>
|
|
|
@ -1,61 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import ModuleMain from 'salix/components/module-main';
|
|
||||||
|
|
||||||
export default class Roadmap extends ModuleMain {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
|
|
||||||
this.include = {
|
|
||||||
relation: 'supplier',
|
|
||||||
scope: {
|
|
||||||
fields: ['nickname']
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
$postLink() {
|
|
||||||
const from = Date.vnNew();
|
|
||||||
from.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const to = Date.vnNew();
|
|
||||||
to.setHours(23, 59, 59, 999);
|
|
||||||
|
|
||||||
this.filterParams = {
|
|
||||||
from: from,
|
|
||||||
to: to
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$.model.addFilter({where: {
|
|
||||||
and: [
|
|
||||||
{etd: {gte: from}},
|
|
||||||
{etd: {lte: to}}
|
|
||||||
]
|
|
||||||
}});
|
|
||||||
}
|
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'search':
|
|
||||||
return /^\d+$/.test(value)
|
|
||||||
? {id: value}
|
|
||||||
: {name: {like: `%${value}%`}};
|
|
||||||
case 'from':
|
|
||||||
return {etd: {gte: value}};
|
|
||||||
case 'to':
|
|
||||||
return {etd: {lte: value}};
|
|
||||||
case 'supplierFk':
|
|
||||||
case 'price':
|
|
||||||
return {[param]: value};
|
|
||||||
case 'tractorPlate':
|
|
||||||
case 'trailerPlate':
|
|
||||||
case 'phone':
|
|
||||||
case 'driverName':
|
|
||||||
return {[param]: {like: `%${value}%`}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRoadmap', {
|
|
||||||
controller: Roadmap,
|
|
||||||
template: require('./index.html')
|
|
||||||
});
|
|
|
@ -1 +0,0 @@
|
||||||
Search roadmap by id or trunk: Buscar troncales por id o troncal
|
|
|
@ -1,74 +0,0 @@
|
||||||
<div class="search-panel">
|
|
||||||
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pt-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="General search"
|
|
||||||
ng-model="filter.search"
|
|
||||||
info="Search routes by id"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<section class="vn-px-md">
|
|
||||||
<vn-horizontal class="manifold-panel vn-pa-md">
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="From"
|
|
||||||
ng-model="filter.from">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="To"
|
|
||||||
ng-model="filter.to">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
</section>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Tractor plate"
|
|
||||||
ng-model="filter.tractorPlate">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Trailer plate"
|
|
||||||
ng-model="filter.trailerPlate">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="filter.supplierFk"
|
|
||||||
url="Suppliers"
|
|
||||||
show-field="nickname"
|
|
||||||
search-function="{or: [{id: $search}, {nickname: {like: '%'+ $search +'%'}}]}"
|
|
||||||
value-field="id"
|
|
||||||
order="nickname"
|
|
||||||
label="Carrier">
|
|
||||||
<tpl-item>
|
|
||||||
{{::id}} - {{::nickname}}
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
label="Price"
|
|
||||||
ng-model="filter.price">
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Driver name"
|
|
||||||
ng-model="filter.driverName">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Phone"
|
|
||||||
ng-model="filter.phone">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pb-lg vn-mt-lg">
|
|
||||||
<vn-submit label="Search"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,7 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
|
|
||||||
ngModule.component('vnRoadmapSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: SearchPanel
|
|
||||||
});
|
|
|
@ -1,71 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="RoadmapStops"
|
|
||||||
where="{roadmapFk: $ctrl.$params.id}"
|
|
||||||
order="eta ASC"
|
|
||||||
data="$ctrl.roadmapStops"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.roadmapStops"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<form class="vn-w-md" name="form" ng-submit="$ctrl.onSubmit()">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal ng-repeat="roadmapStop in $ctrl.roadmapStops">
|
|
||||||
<vn-autocomplete vn-one
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="roadmapStop.warehouseFk"
|
|
||||||
url="Warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
vn-focus
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-date-picker vn-one
|
|
||||||
label="ETA date"
|
|
||||||
ng-model="roadmapStop.eta"
|
|
||||||
rule>
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-input-time
|
|
||||||
vn-one
|
|
||||||
label="ETA hour"
|
|
||||||
ng-model="roadmapStop.eta">
|
|
||||||
</vn-input-time>
|
|
||||||
<vn-textArea
|
|
||||||
vn-one
|
|
||||||
label="Description"
|
|
||||||
ng-model="roadmapStop.description"
|
|
||||||
rule>
|
|
||||||
</vn-textArea>
|
|
||||||
<vn-none>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-tooltip="Remove stop"
|
|
||||||
icon="delete"
|
|
||||||
ng-click="model.remove($index)"
|
|
||||||
tabindex="-1">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-none>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-one>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-bind="+"
|
|
||||||
vn-tooltip="Add stop"
|
|
||||||
icon="add_circle"
|
|
||||||
ng-click="$ctrl.add()">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-one>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="confirm"
|
|
||||||
question="Delete stop?"
|
|
||||||
on-accept="$ctrl.removeTicketFromRoute($index)">
|
|
||||||
</vn-confirm>
|
|
|
@ -1,39 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
add() {
|
|
||||||
const filter = {
|
|
||||||
fields: ['etd']
|
|
||||||
};
|
|
||||||
this.$http.get(`Roadmaps/${this.$params.id}`, {filter})
|
|
||||||
.then(res => {
|
|
||||||
this.roadmap = res.data;
|
|
||||||
|
|
||||||
const eta = new Date(this.roadmap.etd);
|
|
||||||
eta.setDate(eta.getDate() + 1);
|
|
||||||
|
|
||||||
this.$.model.insert({
|
|
||||||
roadmapFk: this.$params.id,
|
|
||||||
eta: eta
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.check();
|
|
||||||
this.$.model.save().then(() => {
|
|
||||||
this.$.watcher.notifySaved();
|
|
||||||
this.$.watcher.updateOriginalData();
|
|
||||||
this.$.model.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnRoadmapStops', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
roadmap: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,4 +0,0 @@
|
||||||
Remove stop: Eliminar parada
|
|
||||||
Add stop: Añadir parada
|
|
||||||
ETA date: Fecha ETA
|
|
||||||
ETA hour: Hora ETA
|
|
|
@ -1,116 +0,0 @@
|
||||||
<vn-card class="summary">
|
|
||||||
<h5>
|
|
||||||
<span>{{summary.id}} - {{summary.name}}</span>
|
|
||||||
</h5>
|
|
||||||
<vn-horizontal class="vn-pa-md">
|
|
||||||
<vn-one>
|
|
||||||
<vn-label-value label="Carrier">
|
|
||||||
<span ng-click="supplierDescriptor.show($event, summary.supplier.id)" class="link">
|
|
||||||
{{summary.supplier.nickname}}
|
|
||||||
</span>
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="ETD"
|
|
||||||
value="{{summary.etd | date:'dd/MM/yyyy HH:mm'}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Tractor plate"
|
|
||||||
value="{{summary.tractorPlate}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Trailer plate"
|
|
||||||
value="{{summary.trailerPlate}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-one>
|
|
||||||
<vn-one>
|
|
||||||
<vn-label-value
|
|
||||||
label="Phone"
|
|
||||||
>
|
|
||||||
<vn-link-phone
|
|
||||||
phone-number="summary.phone"
|
|
||||||
></vn-link-phone>
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Worker"
|
|
||||||
value="{{summary.worker.firstName}} {{summary.worker.lastName}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Observations"
|
|
||||||
value="{{summary.observations}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-one>
|
|
||||||
<vn-auto>
|
|
||||||
<h4>
|
|
||||||
<a
|
|
||||||
ui-sref="route.roadmap.card.stops({id:summary.id})"
|
|
||||||
target="_self">
|
|
||||||
<span translate vn-tooltip="Go to">Stops</span>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-bind="+"
|
|
||||||
vn-tooltip="Add stop"
|
|
||||||
icon="add_circle"
|
|
||||||
vn-click-stop="addRoadmapStop.show()">
|
|
||||||
</vn-icon-button>
|
|
||||||
</a>
|
|
||||||
</h4>
|
|
||||||
<vn-table model="model">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th>Wharehouse</vn-th>
|
|
||||||
<vn-th>ETA</vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr ng-repeat="roadmapStop in summary.roadmapStop">
|
|
||||||
<vn-td>{{roadmapStop.warehouse.name}}</vn-td>
|
|
||||||
<vn-td expand>{{roadmapStop.eta | date:'dd/MM/yyyy HH:mm'}}</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-auto>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-supplier-descriptor-popover
|
|
||||||
vn-id="supplierDescriptor">
|
|
||||||
</vn-supplier-descriptor-popover>
|
|
||||||
|
|
||||||
<vn-dialog
|
|
||||||
vn-id="addRoadmapStop"
|
|
||||||
on-open="$ctrl.getETD()"
|
|
||||||
on-accept="$ctrl.onAddAccept()">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="$ctrl.roadmapStop.warehouseFk"
|
|
||||||
url="Warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
vn-focus
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
label="ETA date"
|
|
||||||
ng-model="$ctrl.roadmapStop.eta"
|
|
||||||
rule>
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-input-time
|
|
||||||
label="ETA hour"
|
|
||||||
ng-model="$ctrl.roadmapStop.eta">
|
|
||||||
</vn-input-time>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textArea
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.roadmapStop.description"
|
|
||||||
rule>
|
|
||||||
</vn-textArea>
|
|
||||||
</vn-horizontal>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Confirm</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
|
@ -1,68 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Component from 'core/lib/component';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Component {
|
|
||||||
set roadmap(value) {
|
|
||||||
this._roadmap = value;
|
|
||||||
this.$.summary = null;
|
|
||||||
if (!value) return;
|
|
||||||
|
|
||||||
this.loadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
get roadmap() {
|
|
||||||
return this._roadmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadData() {
|
|
||||||
const filter = {
|
|
||||||
include: [
|
|
||||||
{relation: 'supplier'},
|
|
||||||
{relation: 'worker'},
|
|
||||||
{relation: 'roadmapStop',
|
|
||||||
scope: {
|
|
||||||
include: [
|
|
||||||
{relation: 'warehouse'}
|
|
||||||
]
|
|
||||||
}}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
this.$http.get(`Roadmaps/${this.roadmap.id}`, {filter})
|
|
||||||
.then(res => this.$.summary = res.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
getETD() {
|
|
||||||
const eta = new Date(this.roadmap.etd);
|
|
||||||
eta.setDate(eta.getDate() + 1);
|
|
||||||
|
|
||||||
this.roadmapStop = {eta: eta};
|
|
||||||
}
|
|
||||||
|
|
||||||
onAddAccept() {
|
|
||||||
try {
|
|
||||||
const data = {
|
|
||||||
roadmapFk: this.roadmap.id,
|
|
||||||
warehouseFk: this.roadmapStop.warehouseFk,
|
|
||||||
eta: this.roadmapStop.eta,
|
|
||||||
description: this.roadmapStop.description
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http.post(`RoadmapStops`, data)
|
|
||||||
.then(() => {
|
|
||||||
this.loadData();
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.vnApp.showError(this.$t(e.message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnRoadmapSummary', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
roadmap: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
Stops: Paradas
|
|
||||||
Wharehouse: Almacén
|
|
||||||
You must fill all the fields: Debes rellenar todos los campos
|
|
|
@ -1,9 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
vn-roadmap-summary .summary {
|
|
||||||
a:not(vn-link-phone a) {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 18.328px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,18 +6,7 @@
|
||||||
"dependencies": ["client", "worker", "ticket", "supplier", "invoiceIn"],
|
"dependencies": ["client", "worker", "ticket", "supplier", "invoiceIn"],
|
||||||
"menus": {
|
"menus": {
|
||||||
"main": [
|
"main": [
|
||||||
{"state": "route.index", "icon": "icon-delivery"},
|
{"state": "route.index", "icon": "icon-delivery"}
|
||||||
{"state": "route.agencyTerm.index", "icon": "icon-agency-term"},
|
|
||||||
{"state": "route.roadmap", "icon": "icon-trailer"}
|
|
||||||
],
|
|
||||||
"card": [
|
|
||||||
{"state": "route.card.basicData", "icon": "settings"},
|
|
||||||
{"state": "route.card.tickets", "icon": "icon-ticket"},
|
|
||||||
{"state": "route.card.log", "icon": "history"}
|
|
||||||
],
|
|
||||||
"roadmap": [
|
|
||||||
{"state": "route.roadmap.card.basicData", "icon": "settings"},
|
|
||||||
{"state": "route.roadmap.card.stops", "icon": "icon-lines"}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"routes": [
|
"routes": [
|
||||||
|
@ -33,108 +22,6 @@
|
||||||
"state": "route.index",
|
"state": "route.index",
|
||||||
"component": "vn-route-index",
|
"component": "vn-route-index",
|
||||||
"description": "Routes"
|
"description": "Routes"
|
||||||
}, {
|
|
||||||
"url": "/create",
|
|
||||||
"state": "route.create",
|
|
||||||
"component": "vn-route-create",
|
|
||||||
"description": "New route"
|
|
||||||
}, {
|
|
||||||
"url": "/:id",
|
|
||||||
"state": "route.card",
|
|
||||||
"abstract": true,
|
|
||||||
"component": "vn-route-card"
|
|
||||||
}, {
|
|
||||||
"url": "/agency-term?q",
|
|
||||||
"abstract": true,
|
|
||||||
"state": "route.agencyTerm",
|
|
||||||
"component": "ui-view"
|
|
||||||
}, {
|
|
||||||
"url": "/index",
|
|
||||||
"state": "route.agencyTerm.index",
|
|
||||||
"component": "vn-agency-term-index",
|
|
||||||
"description": "Autonomous",
|
|
||||||
"acl": ["administrative"]
|
|
||||||
},{
|
|
||||||
"url": "/createInvoiceIn?q",
|
|
||||||
"state": "route.agencyTerm.createInvoiceIn",
|
|
||||||
"component": "vn-agency-term-create-invoice-in",
|
|
||||||
"description": "File management",
|
|
||||||
"params": {
|
|
||||||
"route": "$ctrl.route"
|
|
||||||
},
|
|
||||||
"acl": ["administrative"]
|
|
||||||
}, {
|
|
||||||
"url": "/summary",
|
|
||||||
"state": "route.card.summary",
|
|
||||||
"component": "vn-route-summary",
|
|
||||||
"description": "Summary",
|
|
||||||
"params": {
|
|
||||||
"route": "$ctrl.route"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"url": "/basic-data",
|
|
||||||
"state": "route.card.basicData",
|
|
||||||
"component": "vn-route-basic-data",
|
|
||||||
"description": "Basic data",
|
|
||||||
"params": {
|
|
||||||
"route": "$ctrl.route"
|
|
||||||
},
|
|
||||||
"acl": ["delivery"]
|
|
||||||
}, {
|
|
||||||
"url" : "/log",
|
|
||||||
"state": "route.card.log",
|
|
||||||
"component": "vn-route-log",
|
|
||||||
"description": "Log",
|
|
||||||
"acl": ["delivery"]
|
|
||||||
}, {
|
|
||||||
"url": "/tickets",
|
|
||||||
"state": "route.card.tickets",
|
|
||||||
"component": "vn-route-tickets",
|
|
||||||
"description": "Tickets",
|
|
||||||
"params": {
|
|
||||||
"route": "$ctrl.route"
|
|
||||||
},
|
|
||||||
"acl": ["delivery"]
|
|
||||||
}, {
|
|
||||||
"url": "/roadmap?q",
|
|
||||||
"state": "route.roadmap",
|
|
||||||
"component": "vn-roadmap",
|
|
||||||
"description": "Roadmaps"
|
|
||||||
}, {
|
|
||||||
"url": "/create",
|
|
||||||
"state": "route.roadmap.create",
|
|
||||||
"component": "vn-roadmap-create",
|
|
||||||
"description": "Create roadmap"
|
|
||||||
},{
|
|
||||||
"url": "/:id",
|
|
||||||
"state": "route.roadmap.card",
|
|
||||||
"component": "vn-roadmap-card",
|
|
||||||
"abstract": true,
|
|
||||||
"description": "Detail"
|
|
||||||
},{
|
|
||||||
"url": "/summary",
|
|
||||||
"state": "route.roadmap.card.summary",
|
|
||||||
"component": "vn-roadmap-summary",
|
|
||||||
"description": "Summary",
|
|
||||||
"params": {
|
|
||||||
"roadmap": "$ctrl.roadmap"
|
|
||||||
}
|
|
||||||
},{
|
|
||||||
"url": "/basic-data",
|
|
||||||
"state": "route.roadmap.card.basicData",
|
|
||||||
"component": "vn-roadmap-basic-data",
|
|
||||||
"description": "Basic data",
|
|
||||||
"params": {
|
|
||||||
"roadmap": "$ctrl.roadmap"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"url": "/stops",
|
|
||||||
"state": "route.roadmap.card.stops",
|
|
||||||
"component": "vn-roadmap-stops",
|
|
||||||
"description": "Stops",
|
|
||||||
"params": {
|
|
||||||
"route": "$ctrl.roadmap"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
<div class="search-panel">
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Warehouses"
|
|
||||||
data="warehouses">
|
|
||||||
</vn-crud-model>
|
|
||||||
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pt-lg">
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="General search"
|
|
||||||
ng-model="filter.search"
|
|
||||||
info="Search routes by id"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-worker-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="filter.workerFk"
|
|
||||||
show-field="nickname">
|
|
||||||
</vn-worker-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Agency"
|
|
||||||
ng-model="filter.agencyModeFk"
|
|
||||||
url="AgencyModes/isActive"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<section class="vn-px-md">
|
|
||||||
<vn-horizontal class="manifold-panel vn-pa-md">
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="From"
|
|
||||||
ng-model="filter.from"
|
|
||||||
on-change="$ctrl.from = value">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="To"
|
|
||||||
ng-model="filter.to"
|
|
||||||
on-change="$ctrl.to = value">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-none class="or vn-px-md" translate>Or</vn-none>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
min="0"
|
|
||||||
step="1"
|
|
||||||
label="Days onward"
|
|
||||||
ng-model="filter.scopeDays"
|
|
||||||
on-change="$ctrl.scopeDays = value"
|
|
||||||
display-controls="true">
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-icon color-marginal
|
|
||||||
icon="info"
|
|
||||||
vn-tooltip="Cannot choose a range of dates and days onward at the same time">
|
|
||||||
</vn-icon>
|
|
||||||
</vn-horizontal>
|
|
||||||
</section>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Vehicle"
|
|
||||||
ng-model="filter.vehicleFk"
|
|
||||||
url="Vehicles"
|
|
||||||
show-field="numberPlate"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="m³"
|
|
||||||
ng-model="filter.m3">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg">
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="filter.warehouseFk"
|
|
||||||
data="warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Description"
|
|
||||||
ng-model="filter.description">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-px-lg vn-pb-lg vn-mt-lg">
|
|
||||||
<vn-submit label="Search"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,43 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
|
|
||||||
class Controller extends SearchPanel {
|
|
||||||
constructor($, $element) {
|
|
||||||
super($, $element);
|
|
||||||
this.filter = this.$.filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
get from() {
|
|
||||||
return this._from;
|
|
||||||
}
|
|
||||||
|
|
||||||
set from(value) {
|
|
||||||
this._from = value;
|
|
||||||
this.filter.scopeDays = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
get to() {
|
|
||||||
return this._to;
|
|
||||||
}
|
|
||||||
|
|
||||||
set to(value) {
|
|
||||||
this._to = value;
|
|
||||||
this.filter.scopeDays = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
get scopeDays() {
|
|
||||||
return this._scopeDays;
|
|
||||||
}
|
|
||||||
|
|
||||||
set scopeDays(value) {
|
|
||||||
this._scopeDays = value;
|
|
||||||
|
|
||||||
this.filter.from = null;
|
|
||||||
this.filter.to = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,48 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('Route Component vnRouteSearchPanel', () => {
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject($componentController => {
|
|
||||||
controller = $componentController('vnRouteSearchPanel', {$element: null});
|
|
||||||
controller.$t = () => {};
|
|
||||||
controller.filter = {};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('from() setter', () => {
|
|
||||||
it('should clear the scope days when setting the from property', () => {
|
|
||||||
controller.filter.scopeDays = 1;
|
|
||||||
|
|
||||||
controller.from = Date.vnNew();
|
|
||||||
|
|
||||||
expect(controller.filter.scopeDays).toBeNull();
|
|
||||||
expect(controller.from).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('to() setter', () => {
|
|
||||||
it('should clear the scope days when setting the to property', () => {
|
|
||||||
controller.filter.scopeDays = 1;
|
|
||||||
|
|
||||||
controller.to = Date.vnNew();
|
|
||||||
|
|
||||||
expect(controller.filter.scopeDays).toBeNull();
|
|
||||||
expect(controller.to).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('scopeDays() setter', () => {
|
|
||||||
it('should clear the date range when setting the scopeDays property', () => {
|
|
||||||
controller.filter.from = Date.vnNew();
|
|
||||||
controller.filter.to = Date.vnNew();
|
|
||||||
|
|
||||||
controller.scopeDays = 1;
|
|
||||||
|
|
||||||
expect(controller.filter.from).toBeNull();
|
|
||||||
expect(controller.filter.to).toBeNull();
|
|
||||||
expect(controller.scopeDays).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,36 +0,0 @@
|
||||||
<vn-dialog
|
|
||||||
vn-id="SMSDialog"
|
|
||||||
on-accept="$ctrl.onResponse()"
|
|
||||||
message="Send SMS to the selected tickets">
|
|
||||||
<tpl-body>
|
|
||||||
<section class="SMSDialog">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textarea vn-one
|
|
||||||
vn-id="message"
|
|
||||||
label="Message"
|
|
||||||
ng-model="$ctrl.sms.message"
|
|
||||||
info="Special characters like accents counts as a multiple"
|
|
||||||
rows="5"
|
|
||||||
required="true"
|
|
||||||
rule>
|
|
||||||
</vn-textarea>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<span>
|
|
||||||
{{'Characters remaining' | translate}}:
|
|
||||||
<vn-chip translate-attr="{title: 'Packing'}" ng-class="{
|
|
||||||
'colored': $ctrl.charactersRemaining() > 25,
|
|
||||||
'warning': $ctrl.charactersRemaining() <= 25,
|
|
||||||
'alert': $ctrl.charactersRemaining() < 0,
|
|
||||||
}">
|
|
||||||
{{$ctrl.charactersRemaining()}}
|
|
||||||
</vn-chip>
|
|
||||||
</span>
|
|
||||||
</vn-horizontal>
|
|
||||||
</section>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Send</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
|
@ -1,47 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Component from 'core/lib/component';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Component {
|
|
||||||
open() {
|
|
||||||
this.$.SMSDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
charactersRemaining() {
|
|
||||||
const element = this.$.message;
|
|
||||||
const value = element.input.value;
|
|
||||||
|
|
||||||
const maxLength = 160;
|
|
||||||
const textAreaLength = new Blob([value]).size;
|
|
||||||
return maxLength - textAreaLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
onResponse() {
|
|
||||||
try {
|
|
||||||
if (!this.sms.destination)
|
|
||||||
throw new Error(`The destination can't be empty`);
|
|
||||||
if (!this.sms.message)
|
|
||||||
throw new Error(`The message can't be empty`);
|
|
||||||
if (this.charactersRemaining() < 0)
|
|
||||||
throw new Error(`The message it's too long`);
|
|
||||||
|
|
||||||
this.$http.post(`Routes/sendSms`, this.sms).then(res => {
|
|
||||||
this.vnApp.showMessage(this.$t('SMS sent'));
|
|
||||||
|
|
||||||
if (res.data) this.emit('send', {response: res.data});
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.vnApp.showError(this.$t(e.message));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteSms', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
sms: '<',
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,71 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('Route', () => {
|
|
||||||
describe('Component vnRouteSms', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
let $scope = $rootScope.$new();
|
|
||||||
const $element = angular.element('<vn-dialog></vn-dialog>');
|
|
||||||
controller = $componentController('vnRouteSms', {$element, $scope});
|
|
||||||
controller.$.message = {
|
|
||||||
input: {
|
|
||||||
value: 'My SMS'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('onResponse()', () => {
|
|
||||||
it('should perform a POST query and show a success snackbar', () => {
|
|
||||||
let params = {destinationFk: 1101, destination: 111111111, message: 'My SMS'};
|
|
||||||
controller.sms = {destinationFk: 1101, destination: 111111111, message: 'My SMS'};
|
|
||||||
|
|
||||||
jest.spyOn(controller.vnApp, 'showMessage');
|
|
||||||
$httpBackend.expect('POST', `Routes/sendSms`, params).respond(200, params);
|
|
||||||
|
|
||||||
controller.onResponse();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onResponse without the destination and show an error snackbar', () => {
|
|
||||||
controller.sms = {destinationFk: 1101, message: 'My SMS'};
|
|
||||||
|
|
||||||
jest.spyOn(controller.vnApp, 'showError');
|
|
||||||
|
|
||||||
controller.onResponse();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith(`The destination can't be empty`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call onResponse without the message and show an error snackbar', () => {
|
|
||||||
controller.sms = {destinationFk: 1101, destination: 222222222};
|
|
||||||
|
|
||||||
jest.spyOn(controller.vnApp, 'showError');
|
|
||||||
|
|
||||||
controller.onResponse();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith(`The message can't be empty`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('charactersRemaining()', () => {
|
|
||||||
it('should return the characters remaining in a element', () => {
|
|
||||||
controller.$.message = {
|
|
||||||
input: {
|
|
||||||
value: 'My message 0€'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = controller.charactersRemaining();
|
|
||||||
|
|
||||||
expect(result).toEqual(145);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,9 +0,0 @@
|
||||||
Send SMS to the selected tickets: Enviar SMS a los tickets seleccionados
|
|
||||||
Routes to notify: Rutas a notificar
|
|
||||||
Message: Mensaje
|
|
||||||
SMS sent!: ¡SMS enviado!
|
|
||||||
Characters remaining: Carácteres restantes
|
|
||||||
The destination can't be empty: El destinatario no puede estar vacio
|
|
||||||
The message can't be empty: El mensaje no puede estar vacio
|
|
||||||
The message it's too long: El mensaje es demasiado largo
|
|
||||||
Special characters like accents counts as a multiple: Carácteres especiales como los acentos cuentan como varios
|
|
|
@ -1,5 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
.SMSDialog {
|
|
||||||
min-width: 400px
|
|
||||||
}
|
|
|
@ -1,145 +0,0 @@
|
||||||
<vn-card class="summary">
|
|
||||||
<h5>
|
|
||||||
<a ng-if="::$ctrl.summary.route.id"
|
|
||||||
vn-tooltip="Go to the route"
|
|
||||||
ui-sref="route.card.summary({id: {{::$ctrl.summary.route.id}}})"
|
|
||||||
name="goToSummary">
|
|
||||||
<vn-icon-button icon="launch"></vn-icon-button>
|
|
||||||
</a>
|
|
||||||
<span>{{$ctrl.summary.route.id}} - {{$ctrl.summary.route.description}}</span>
|
|
||||||
</h5>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-one>
|
|
||||||
<vn-label-value label="Id"
|
|
||||||
value="{{$ctrl.summary.route.id}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Date"
|
|
||||||
value="{{$ctrl.summary.route.created | date: 'dd/MM/yyyy'}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Agency"
|
|
||||||
value="{{$ctrl.summary.route.agencyMode.name}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Vehicle"
|
|
||||||
value="{{$ctrl.summary.route.vehicle.numberPlate}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Driver">
|
|
||||||
<span
|
|
||||||
ng-click="workerDescriptor.show($event, $ctrl.summary.route.workerFk)"
|
|
||||||
class="link">
|
|
||||||
{{$ctrl.summary.route.worker.user.name}}
|
|
||||||
</span>
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Cost"
|
|
||||||
value="{{$ctrl.summary.route.cost | currency: 'EUR':2}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-one>
|
|
||||||
<vn-one>
|
|
||||||
<vn-label-value label="Starting time"
|
|
||||||
value="{{$ctrl.summary.route.started | date: 'HH:mm'}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Finishing time"
|
|
||||||
value="{{$ctrl.summary.route.finished | date: 'HH:mm'}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Km Start"
|
|
||||||
value="{{$ctrl.summary.route.kmStart}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Km End"
|
|
||||||
value="{{$ctrl.summary.route.kmEnd}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Volume"
|
|
||||||
value="{{$ctrl.summary.route.m3 | dashIfEmpty}} / {{$ctrl.summary.route.vehicle.m3 | dashIfEmpty}} m³">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Packages"
|
|
||||||
value="{{$ctrl.packagesTotal}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-one>
|
|
||||||
<vn-one>
|
|
||||||
<vn-textarea
|
|
||||||
disabled="true"
|
|
||||||
label="Description"
|
|
||||||
ng-model="$ctrl.summary.route.description">
|
|
||||||
</vn-textarea>
|
|
||||||
</vn-one>
|
|
||||||
<vn-auto>
|
|
||||||
<h4 ng-show="$ctrl.isDelivery">
|
|
||||||
<a
|
|
||||||
ui-sref="route.card.tickets({id:$ctrl.route.id})"
|
|
||||||
target="_self">
|
|
||||||
<span translate vn-tooltip="Go to">Ticket</span>
|
|
||||||
</a>
|
|
||||||
</h4>
|
|
||||||
<h4
|
|
||||||
translate
|
|
||||||
ng-show="!$ctrl.isDelivery">
|
|
||||||
Ticket
|
|
||||||
</h4>
|
|
||||||
<vn-table model="model">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th shrink>Order</vn-th>
|
|
||||||
<vn-th>Street</vn-th>
|
|
||||||
<vn-th>City</vn-th>
|
|
||||||
<vn-th shrink>PC</vn-th>
|
|
||||||
<vn-th>Client</vn-th>
|
|
||||||
<vn-th>State</vn-th>
|
|
||||||
<vn-th number shrink>Packages</vn-th>
|
|
||||||
<vn-th shrink>m³</vn-th>
|
|
||||||
<vn-th shrink>Packaging</vn-th>
|
|
||||||
<vn-th number>Ticket</vn-th>
|
|
||||||
<vn-th shrink></vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr ng-repeat="ticket in $ctrl.summary.tickets">
|
|
||||||
<vn-td shrink>{{ticket.priority | dashIfEmpty}}</vn-td>
|
|
||||||
<vn-td expand title="{{ticket.address.street}}">{{ticket.street}}</vn-td>
|
|
||||||
<vn-td
|
|
||||||
expand
|
|
||||||
ng-click="$ctrl.goToBuscaman(ticket)"
|
|
||||||
class="link"
|
|
||||||
vn-tooltip="Open buscaman"
|
|
||||||
tooltip-position="up">
|
|
||||||
{{::ticket.city}}
|
|
||||||
</vn-td>
|
|
||||||
<vn-td shrink>{{ticket.postalCode}}</vn-td>
|
|
||||||
<vn-td>
|
|
||||||
<span
|
|
||||||
ng-click="clientDescriptor.show($event, ticket.clientFk)"
|
|
||||||
class="link">
|
|
||||||
{{ticket.nickname}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>{{ticket.ticketStateName}}</vn-td>
|
|
||||||
<vn-td number shrink>{{ticket.packages}}</vn-td>
|
|
||||||
<vn-td shrink>{{ticket.volume}}</vn-td>
|
|
||||||
<vn-td shrink>{{ticket.ipt}}</vn-td>
|
|
||||||
<vn-td number>
|
|
||||||
<span
|
|
||||||
ng-click="ticketDescriptor.show($event, ticket.id)"
|
|
||||||
class="link">
|
|
||||||
{{ticket.id}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>
|
|
||||||
<vn-icon-button
|
|
||||||
ng-if="::ticket.description"
|
|
||||||
vn-tooltip="{{::ticket.description}}"
|
|
||||||
icon="icon-notes"
|
|
||||||
tabindex="-1">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-auto>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-ticket-descriptor-popover
|
|
||||||
vn-id="ticketDescriptor">
|
|
||||||
</vn-ticket-descriptor-popover>
|
|
||||||
<vn-client-descriptor-popover
|
|
||||||
vn-id="clientDescriptor">
|
|
||||||
</vn-client-descriptor-popover>
|
|
||||||
<vn-worker-descriptor-popover
|
|
||||||
vn-id="workerDescriptor">
|
|
||||||
</vn-worker-descriptor-popover>
|
|
|
@ -1,57 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Summary from 'salix/components/summary';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Summary {
|
|
||||||
set route(value) {
|
|
||||||
this._route = value;
|
|
||||||
if (value && value.id)
|
|
||||||
this.getSummary();
|
|
||||||
}
|
|
||||||
|
|
||||||
sumPackages() {
|
|
||||||
this.packagesTotal = 0;
|
|
||||||
this.summary.tickets.forEach(ticket => {
|
|
||||||
this.packagesTotal += ticket.packages;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get isDelivery() {
|
|
||||||
return this.aclService.hasAny(['delivery']);
|
|
||||||
}
|
|
||||||
|
|
||||||
get route() {
|
|
||||||
return this._route;
|
|
||||||
}
|
|
||||||
|
|
||||||
getSummary() {
|
|
||||||
this.$http.get(`Routes/${this.route.id}/summary`).then(response => {
|
|
||||||
this.summary = response.data;
|
|
||||||
if (response.data && response.data.tickets)
|
|
||||||
this.sumPackages();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
goToBuscaman(ticket) {
|
|
||||||
if (!this.route.vehicleFk)
|
|
||||||
throw new UserError(`The route doesn't have a vehicle`);
|
|
||||||
let query = `Routes/${this.route.vehicleFk}/getDeliveryPoint`;
|
|
||||||
|
|
||||||
this.$http.get(query).then(response => {
|
|
||||||
if (!response.data)
|
|
||||||
throw new UserError(`The route's vehicle doesn't have a delivery point`);
|
|
||||||
|
|
||||||
const address = response.data + '+to:' + ticket.postalCode + ' ' + ticket.city + ' ' + ticket.street;
|
|
||||||
const url = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=';
|
|
||||||
window.open(url + encodeURI(address), '_blank');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteSummary', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
route: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,65 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Route', () => {
|
|
||||||
describe('Component summary', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
const $element = angular.element('<vn-route-summary></vn-route-summary>');
|
|
||||||
controller = $componentController('vnRouteSummary', {$element});
|
|
||||||
controller.route = {id: 1};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('getSummary()', () => {
|
|
||||||
it('should perform a query to set summary', () => {
|
|
||||||
$httpBackend.when('GET', `Routes/1/summary`).respond(200, 24);
|
|
||||||
controller.getSummary();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.summary).toEqual(24);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('sumPackages()', () => {
|
|
||||||
it('should calculate the packages total', () => {
|
|
||||||
controller.summary = {
|
|
||||||
tickets: [
|
|
||||||
{packages: 3},
|
|
||||||
{packages: 1}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
controller.sumPackages();
|
|
||||||
|
|
||||||
expect(controller.packagesTotal).toEqual(4);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('goToBuscaman()', () => {
|
|
||||||
it('should open buscaman with the given arguments', () => {
|
|
||||||
jest.spyOn(window, 'open').mockReturnThis();
|
|
||||||
const expectedUrl = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=46460%20Av%20Espioca%20100+to:n19%20London%20my%20street';
|
|
||||||
controller.route = {vehicleFk: 1};
|
|
||||||
const url = `Routes/${controller.route.vehicleFk}/getDeliveryPoint`;
|
|
||||||
$httpBackend.when('GET', `Routes/1/summary`).respond();
|
|
||||||
$httpBackend.expectGET(url).respond('46460 Av Espioca 100');
|
|
||||||
|
|
||||||
const ticket = {
|
|
||||||
id: 1,
|
|
||||||
checked: true,
|
|
||||||
street: 'my street',
|
|
||||||
postalCode: 'n19',
|
|
||||||
city: 'London'
|
|
||||||
};
|
|
||||||
|
|
||||||
controller.goToBuscaman(ticket);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(window.open).toHaveBeenCalledWith(expectedUrl, '_blank');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,9 +0,0 @@
|
||||||
Driver: Conductor
|
|
||||||
Vehicle: Vehículo
|
|
||||||
Packages: Bultos
|
|
||||||
Starting time: H. Inicio
|
|
||||||
Finishing time: H. Fin
|
|
||||||
Km Start: Km de inicio
|
|
||||||
Km End: Km de fin
|
|
||||||
PC: CP
|
|
||||||
Go to the route: Ir a la ruta
|
|
|
@ -1,6 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
|
|
||||||
vn-route-summary .summary {
|
|
||||||
max-width: $width-lg;
|
|
||||||
}
|
|
|
@ -1,84 +0,0 @@
|
||||||
|
|
||||||
<tpl-title>
|
|
||||||
<vn-horizontal>
|
|
||||||
<span translate>Tickets to add</span>
|
|
||||||
<div class="button-right">
|
|
||||||
<vn-button label="Add" ng-click="$ctrl.setTicketsRoute()"></vn-button>
|
|
||||||
</div>
|
|
||||||
</vn-horizontal>
|
|
||||||
</tpl-title>
|
|
||||||
<tpl-body id="manifold-form">
|
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="Routes/{{$ctrl.route.id}}/getSuggestedTickets"
|
|
||||||
data="$ctrl.possibleTickets"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-data-viewer data="$ctrl.possibleTickets" class="manifold-panel">
|
|
||||||
<vn-table auto-load="true">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th shrink>
|
|
||||||
<vn-multi-check
|
|
||||||
model="model">
|
|
||||||
</vn-multi-check>
|
|
||||||
</vn-th>
|
|
||||||
<vn-th number>Ticket</vn-th>
|
|
||||||
<vn-th>Client</vn-th>
|
|
||||||
<vn-th shrink>Province</vn-th>
|
|
||||||
<vn-th shrink>
|
|
||||||
<span translate>
|
|
||||||
Population
|
|
||||||
</span>
|
|
||||||
</vn-th>
|
|
||||||
<vn-th expand>PC</vn-th>
|
|
||||||
<vn-th>Address</vn-th>
|
|
||||||
<vn-th shrink>Zone</vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr ng-repeat="ticket in $ctrl.possibleTickets">
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-check
|
|
||||||
ng-model="ticket.checked">
|
|
||||||
</vn-check>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td number>
|
|
||||||
<span class="link" ng-click="ticketDescriptor.show($event, ticket.id)">
|
|
||||||
{{::ticket.id}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td expand>
|
|
||||||
<span class="link" ng-click="clientDescriptor.show($event, ticket.clientFk)">
|
|
||||||
{{::ticket.nickname}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td shrink>{{::ticket.address.province.name}}</vn-td>
|
|
||||||
<vn-td shrink>{{::ticket.address.city}}</vn-td>
|
|
||||||
<vn-td number shrink>{{::ticket.address.postalCode}}</vn-td>
|
|
||||||
<vn-td expand title="{{::ticket.address.street}}">{{::ticket.address.street}}</vn-td>
|
|
||||||
<vn-td expand>
|
|
||||||
{{::ticket.zone.name}}
|
|
||||||
<vn-icon-button
|
|
||||||
icon="link_off"
|
|
||||||
class="pointer"
|
|
||||||
title="{{'Unlink zone' | translate: {zoneName: ticket.zone.name, agencyName: ticket.agencyName} }}"
|
|
||||||
ng-click="unlinkZoneConfirmation.show(ticket)">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="unlinkZoneConfirmation"
|
|
||||||
on-accept="$ctrl.unlinkZone($data)"
|
|
||||||
question="{{$ctrl.confirmationMessage}}"
|
|
||||||
message="Unlink selected zone?">
|
|
||||||
</vn-confirm>
|
|
||||||
<vn-ticket-descriptor-popover vn-id="ticket-descriptor">
|
|
||||||
</vn-ticket-descriptor-popover>
|
|
||||||
<vn-client-descriptor-popover vn-id="client-descriptor">
|
|
||||||
</vn-client-descriptor-popover>
|
|
||||||
</tpl-body>
|
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Dialog from 'core/components/dialog';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Dialog {
|
|
||||||
constructor($element, $, $transclude) {
|
|
||||||
super($element, $, $transclude);
|
|
||||||
}
|
|
||||||
|
|
||||||
getSelectedTickets(tickets) {
|
|
||||||
const selectedTickets = [];
|
|
||||||
|
|
||||||
if (tickets) {
|
|
||||||
for (let i = 0; i < tickets.length; i++) {
|
|
||||||
if (tickets[i].checked)
|
|
||||||
selectedTickets.push(tickets[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return selectedTickets;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateVolume() {
|
|
||||||
let url = `Routes/${this.route.id}/updateVolume`;
|
|
||||||
this.$http.post(url).then(() => {
|
|
||||||
this.$.model.refresh();
|
|
||||||
if (this.parentReload)
|
|
||||||
this.parentReload();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setTicketsRoute() {
|
|
||||||
const tickets = this.getSelectedTickets(this.possibleTickets);
|
|
||||||
if (tickets.length === 0) return;
|
|
||||||
|
|
||||||
const updates = [];
|
|
||||||
|
|
||||||
for (let ticket of tickets) {
|
|
||||||
delete ticket.checked;
|
|
||||||
const update = {
|
|
||||||
where: {id: ticket.id},
|
|
||||||
data: {routeFk: this.route.id}
|
|
||||||
};
|
|
||||||
|
|
||||||
updates.push(update);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = {creates: [], updates: updates, deletes: []};
|
|
||||||
return this.$http.post(`Tickets/crud`, data)
|
|
||||||
.then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
this.updateVolume();
|
|
||||||
this.hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
unlinkZone(ticket) {
|
|
||||||
const params = {
|
|
||||||
agencyModeId: this.route.agencyModeFk,
|
|
||||||
zoneId: ticket.zoneFk,
|
|
||||||
};
|
|
||||||
|
|
||||||
const query = `Routes/unlink`;
|
|
||||||
this.$http.post(query, params).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
this.$.model.refresh();
|
|
||||||
this.hide();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controller.$inject = ['$element', '$scope', '$transclude'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteTicketPopup', {
|
|
||||||
slotTemplate: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
route: '<',
|
|
||||||
model: '<?',
|
|
||||||
parentReload: '&'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,82 +0,0 @@
|
||||||
/* eslint max-len: ["error", { "code": 150 }]*/
|
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('Route', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
let $scope;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
const $element = angular.element('<vn-route-ticket-popup></vn-route-ticket-popup>');
|
|
||||||
const $transclude = {
|
|
||||||
$$boundTransclude: {
|
|
||||||
$$slots: []
|
|
||||||
}
|
|
||||||
};
|
|
||||||
controller = $componentController('vnRouteTicketPopup', {$element, $scope, $transclude});
|
|
||||||
controller.route = {id: 1};
|
|
||||||
controller.$.model = {
|
|
||||||
refresh: () => {},
|
|
||||||
remove: () => {}
|
|
||||||
};
|
|
||||||
controller.card = {reload: () => {}};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('unlink()', () => {
|
|
||||||
it('should call the route unlink endpoint with the agency and zone ids', () => {
|
|
||||||
controller.$.model = {refresh: jest.fn()};
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
jest.spyOn(controller, 'hide');
|
|
||||||
|
|
||||||
controller.route = {
|
|
||||||
agencyModeFk: 1
|
|
||||||
};
|
|
||||||
|
|
||||||
const ticket = {
|
|
||||||
zoneFk: 2,
|
|
||||||
};
|
|
||||||
const params = {
|
|
||||||
agencyModeId: controller.route.agencyModeFk,
|
|
||||||
zoneId: ticket.zoneFk,
|
|
||||||
};
|
|
||||||
|
|
||||||
$httpBackend.expectPOST(`Routes/unlink`, params).respond('ok');
|
|
||||||
controller.unlinkZone(ticket);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.hide).toHaveBeenCalled();
|
|
||||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setTicketsRoute()', () => {
|
|
||||||
it('should perform a POST query to add tickets to the route', () => {
|
|
||||||
controller.$.model = {refresh: jest.fn()};
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
jest.spyOn(controller, 'hide');
|
|
||||||
|
|
||||||
controller.route = {id: 111};
|
|
||||||
|
|
||||||
controller.possibleTickets = [
|
|
||||||
{id: 2, checked: false},
|
|
||||||
{id: 3, checked: true},
|
|
||||||
{id: 4, checked: false},
|
|
||||||
{id: 5, checked: true},
|
|
||||||
];
|
|
||||||
|
|
||||||
$httpBackend.whenPOST(`Routes/${controller.route.id}/updateVolume`).respond(200);
|
|
||||||
$httpBackend.expectPOST('Tickets/crud').respond();
|
|
||||||
controller.setTicketsRoute();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.hide).toHaveBeenCalled();
|
|
||||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
.dialog{
|
|
||||||
padding: $float-spacing
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`Route getSelectedItems() should return the selected items 1`] = `
|
|
||||||
Array [
|
|
||||||
Object {
|
|
||||||
"checked": true,
|
|
||||||
"id": 1,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"checked": true,
|
|
||||||
"id": 3,
|
|
||||||
},
|
|
||||||
Object {
|
|
||||||
"checked": true,
|
|
||||||
"id": 5,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
`;
|
|
|
@ -1,203 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="Routes/getTickets"
|
|
||||||
filter="{id: $ctrl.$params.id}"
|
|
||||||
order="priority ASC"
|
|
||||||
data="$ctrl.tickets"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="model">
|
|
||||||
<form
|
|
||||||
class="vn-w-xl"
|
|
||||||
name="form">
|
|
||||||
<vn-card>
|
|
||||||
<section class="vn-pa-md">
|
|
||||||
<vn-tool-bar>
|
|
||||||
<vn-button
|
|
||||||
icon="icon-wand"
|
|
||||||
ng-click="$ctrl.guessPriority()"
|
|
||||||
vn-tooltip="Sort routes">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
disabled="!$ctrl.isChecked"
|
|
||||||
ng-click="$ctrl.goToBuscaman()"
|
|
||||||
vn-tooltip="Open buscaman"
|
|
||||||
icon="icon-buscaman">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
disabled="!$ctrl.isChecked"
|
|
||||||
ng-click="$ctrl.deletePriority()"
|
|
||||||
vn-tooltip="Delete priority"
|
|
||||||
icon="filter_alt">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
ng-click="$ctrl.setOrderedPriority($ctrl.tickets)"
|
|
||||||
vn-tooltip="Renumber all tickets in the order you see on the screen"
|
|
||||||
icon="format_list_numbered">
|
|
||||||
</vn-button>
|
|
||||||
<vn-button
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
vn-acl-action="remove"
|
|
||||||
disabled="!$ctrl.isChecked"
|
|
||||||
icon="sms"
|
|
||||||
vn-tooltip="Send SMS to all clients"
|
|
||||||
ng-click="$ctrl.sendSms()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-tool-bar>
|
|
||||||
<vn-table class="vn-pt-md" model="model" auto-load="false" vn-droppable="$ctrl.onDrop($event)">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th shrink>
|
|
||||||
<vn-multi-check
|
|
||||||
model="model">
|
|
||||||
</vn-multi-check>
|
|
||||||
</vn-th>
|
|
||||||
<vn-th shrink></vn-th>
|
|
||||||
<vn-th field="priority">Order</vn-th>
|
|
||||||
<vn-th field="street" expand>Street</vn-th>
|
|
||||||
<vn-th field="city">City</vn-th>
|
|
||||||
<vn-th field="postalCode" translate-attr="{title: 'Postcode'}" shrink>PC</vn-th>
|
|
||||||
<vn-th field="nickname" expand>Client</vn-th>
|
|
||||||
<vn-th field="warehouse" expand>Warehouse</vn-th>
|
|
||||||
<vn-th field="packages" shrink>Packages</vn-th>
|
|
||||||
<vn-th field="volume" shrink>m³</vn-th>
|
|
||||||
<vn-th field="packaging" shrink>Packaging</vn-th>
|
|
||||||
<vn-th field="id" number>Ticket</vn-th>
|
|
||||||
<vn-th shrink></vn-th>
|
|
||||||
<vn-th shrink></vn-th>
|
|
||||||
<vn-th shrink></vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr ng-repeat="ticket in $ctrl.tickets">
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-check
|
|
||||||
ng-model="ticket.checked">
|
|
||||||
</vn-check>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>
|
|
||||||
<vn-icon-button
|
|
||||||
icon="low_priority"
|
|
||||||
ng-click="$ctrl.setHighestPriority(ticket)"
|
|
||||||
vn-tooltip="Assign highest priority"
|
|
||||||
tabindex="-1">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td-editable number>
|
|
||||||
<text>
|
|
||||||
<strong>{{ticket.priority}}</strong>
|
|
||||||
</text>
|
|
||||||
<field>
|
|
||||||
<vn-input-number
|
|
||||||
rule="Ticket"
|
|
||||||
ng-model="ticket.priority"
|
|
||||||
on-change="$ctrl.setPriority(ticket.id, ticket.priority)"
|
|
||||||
step="1"
|
|
||||||
class="dense"
|
|
||||||
vn-focus>
|
|
||||||
</vn-input-number>
|
|
||||||
</field>
|
|
||||||
</vn-td-editable>
|
|
||||||
<vn-td expand title="{{::ticket.street}}">{{::ticket.street}}</vn-td>
|
|
||||||
<vn-td
|
|
||||||
expand
|
|
||||||
ng-click="$ctrl.goToBuscaman(ticket)"
|
|
||||||
class="link"
|
|
||||||
vn-tooltip="Open buscaman"
|
|
||||||
tooltip-position="up">
|
|
||||||
{{::ticket.city}}
|
|
||||||
</vn-td>
|
|
||||||
<vn-td shrink>{{::ticket.postalCode}}</vn-td>
|
|
||||||
<vn-td expand>
|
|
||||||
<span
|
|
||||||
ng-click="clientDescriptor.show($event, ticket.clientFk)"
|
|
||||||
class="link">
|
|
||||||
{{::ticket.nickname}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>{{ticket.warehouseName}}</vn-td>
|
|
||||||
<vn-td shrink>{{::ticket.packages}}</vn-td>
|
|
||||||
<vn-td shrink>{{::ticket.volume | number:2}}</vn-td>
|
|
||||||
<vn-td shrink>{{::ticket.ipt}}</vn-td>
|
|
||||||
<vn-td number>
|
|
||||||
<span
|
|
||||||
ng-click="ticketDescriptor.show($event, ticket.id)"
|
|
||||||
class="link">
|
|
||||||
{{::ticket.id}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-icon
|
|
||||||
ng-if="::ticket.notes.length"
|
|
||||||
title="{{::ticket.notes[0].description}}"
|
|
||||||
icon="insert_drive_file"
|
|
||||||
class="bright">
|
|
||||||
</vn-icon>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>
|
|
||||||
<vn-icon-button
|
|
||||||
translate-attr="{title: 'Remove ticket'}"
|
|
||||||
icon="delete"
|
|
||||||
ng-click="$ctrl.showDeleteConfirm(ticket.id)"
|
|
||||||
tabindex="-1">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td>
|
|
||||||
<vn-icon-button
|
|
||||||
ng-if="::ticket.description"
|
|
||||||
vn-tooltip="{{::ticket.description}}"
|
|
||||||
icon="icon-notes"
|
|
||||||
tabindex="-1">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
</a>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</section>
|
|
||||||
</vn-card>
|
|
||||||
</form>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-ticket-descriptor-popover
|
|
||||||
vn-id="ticketDescriptor">
|
|
||||||
</vn-ticket-descriptor-popover>
|
|
||||||
<vn-client-descriptor-popover
|
|
||||||
vn-id="clientDescriptor">
|
|
||||||
</vn-client-descriptor-popover>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="confirm"
|
|
||||||
question="Delete ticket from route?"
|
|
||||||
on-accept="$ctrl.removeTicketFromRoute($index)">
|
|
||||||
</vn-confirm>
|
|
||||||
|
|
||||||
<vn-route-ticket-popup
|
|
||||||
vn-id="ticketPopup"
|
|
||||||
route="$ctrl.$params"
|
|
||||||
parent-reload="$ctrl.$.model.refresh()">
|
|
||||||
</vn-route-ticket-popup>
|
|
||||||
<div fixed-bottom-right>
|
|
||||||
<vn-vertical style="align-items: center;">
|
|
||||||
<a vn-bind="+">
|
|
||||||
<vn-button
|
|
||||||
class="round md vn-mb-sm"
|
|
||||||
ng-click="$ctrl.$.ticketPopup.show()"
|
|
||||||
icon="add"
|
|
||||||
vn-tooltip="Add ticket"
|
|
||||||
vn-acl="delivery"
|
|
||||||
vn-acl-action="remove"
|
|
||||||
tooltip-position="left">
|
|
||||||
</vn-button>
|
|
||||||
</a>
|
|
||||||
</vn-vertical>
|
|
||||||
</div>
|
|
||||||
<vn-ticket-descriptor-popover
|
|
||||||
vn-id="ticket-descriptor">
|
|
||||||
</vn-ticket-descriptor-popover>
|
|
||||||
<vn-client-descriptor-popover
|
|
||||||
vn-id="client-descriptor">
|
|
||||||
</vn-client-descriptor-popover>
|
|
||||||
<!-- SMS Dialog -->
|
|
||||||
<vn-route-sms
|
|
||||||
vn-id="sms"
|
|
||||||
sms="$ctrl.newSMS">
|
|
||||||
</vn-route-sms>
|
|
|
@ -1,201 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
import UserError from 'core/lib/user-error';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
get isChecked() {
|
|
||||||
if (this.tickets) {
|
|
||||||
for (let instance of this.tickets)
|
|
||||||
if (instance.checked) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
getHighestPriority() {
|
|
||||||
let highestPriority = Math.max(...this.$.model.data.map(tag => {
|
|
||||||
return tag.priority;
|
|
||||||
}));
|
|
||||||
return highestPriority + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
setHighestPriority(ticket) {
|
|
||||||
const highestPriority = this.getHighestPriority();
|
|
||||||
if (highestPriority - 1 != ticket.priority) {
|
|
||||||
const params = {priority: highestPriority};
|
|
||||||
const query = `Tickets/${ticket.id}/`;
|
|
||||||
this.$http.patch(query, params).then(res => {
|
|
||||||
ticket.priority = res.data.priority;
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setPriority(id, priority) {
|
|
||||||
let params = {priority: priority};
|
|
||||||
let query = `Tickets/${id}/`;
|
|
||||||
this.$http.patch(query, params).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
deletePriority() {
|
|
||||||
const lines = this.getSelectedItems(this.tickets);
|
|
||||||
|
|
||||||
for (const line of lines) {
|
|
||||||
this.$http.patch(`Tickets/${line.id}/`, {priority: null}).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
this.$.model.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setOrderedPriority(lines) {
|
|
||||||
let priority = 1;
|
|
||||||
for (const line of lines) {
|
|
||||||
this.$http.patch(`Tickets/${line.id}/`, {priority: priority}).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
this.$.model.refresh();
|
|
||||||
});
|
|
||||||
priority++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getSelectedItems(items) {
|
|
||||||
const selectedItems = [];
|
|
||||||
|
|
||||||
if (items) {
|
|
||||||
for (let i = 0; i < items.length; i++) {
|
|
||||||
if (items[i].checked)
|
|
||||||
selectedItems.push(items[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return selectedItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
goToBuscaman(ticket) {
|
|
||||||
if (!this.route.vehicleFk)
|
|
||||||
throw new UserError(`The route doesn't have a vehicle`);
|
|
||||||
|
|
||||||
this.$http.get(`Routes/${this.route.vehicleFk}/getDeliveryPoint`).then(res => {
|
|
||||||
if (!res.data)
|
|
||||||
throw new UserError(`The route's vehicle doesn't have a delivery point`);
|
|
||||||
|
|
||||||
let addresses = res.data;
|
|
||||||
const lines = ticket ? [ticket] : this.getSelectedItems(this.tickets);
|
|
||||||
lines.forEach((line, index) => {
|
|
||||||
const previousLine = lines[index - 1] ? lines[index - 1].street : null;
|
|
||||||
if (previousLine != line.street)
|
|
||||||
addresses = addresses + '+to:' + line.postalCode + ' ' + line.city + ' ' + line.street;
|
|
||||||
});
|
|
||||||
|
|
||||||
const url = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=';
|
|
||||||
window.open(url + encodeURI(addresses), '_blank');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
showDeleteConfirm(id) {
|
|
||||||
this.selectedTicket = id;
|
|
||||||
this.$.confirm.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
removeTicketFromRoute($index) {
|
|
||||||
let params = {routeFk: null};
|
|
||||||
let query = `Tickets/${this.selectedTicket}/`;
|
|
||||||
this.$http.patch(query, params).then(() => {
|
|
||||||
this.$.model.remove($index);
|
|
||||||
this.vnApp.showSuccess(this.$t('Ticket removed from route'));
|
|
||||||
this.updateVolume();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
updateVolume() {
|
|
||||||
let url = `Routes/${this.$params.id}/updateVolume`;
|
|
||||||
this.$http.post(url).then(() => {
|
|
||||||
this.card.reload();
|
|
||||||
this.$.model.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
guessPriority() {
|
|
||||||
let query = `Routes/${this.$params.id}/guessPriority/`;
|
|
||||||
this.$http.patch(query).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Order changed'));
|
|
||||||
this.$.model.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onDrop($event) {
|
|
||||||
const ticketId = $event.dataTransfer.getData('Text');
|
|
||||||
|
|
||||||
if (isNaN(ticketId)) {
|
|
||||||
const regexp = new RegExp(/\/ticket\/([0-9]+)\//i);
|
|
||||||
const matches = ticketId.match(regexp);
|
|
||||||
|
|
||||||
if (matches && matches.length)
|
|
||||||
this.insert(matches[1]);
|
|
||||||
else
|
|
||||||
this.vnApp.showError(this.$t('Ticket not found'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isNaN(ticketId))
|
|
||||||
this.insert(ticketId);
|
|
||||||
}
|
|
||||||
|
|
||||||
insert(ticketId) {
|
|
||||||
ticketId = parseInt(ticketId);
|
|
||||||
|
|
||||||
const query = `Routes/${this.route.id}/insertTicket`;
|
|
||||||
return this.$http.patch(query, {ticketId}).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
this.updateVolume();
|
|
||||||
}).catch(error => {
|
|
||||||
if (error.status == 404)
|
|
||||||
return this.vnApp.showError(this.$t('Ticket not found'));
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async sendSms() {
|
|
||||||
try {
|
|
||||||
const clientsFk = [];
|
|
||||||
const clientsName = [];
|
|
||||||
const clients = [];
|
|
||||||
|
|
||||||
const selectedTickets = this.getSelectedItems(this.$.$ctrl.tickets);
|
|
||||||
|
|
||||||
for (let ticket of selectedTickets) {
|
|
||||||
clientsFk.push(ticket.clientFk);
|
|
||||||
let userContact = await this.$http.get(`Clients/${ticket.clientFk}`);
|
|
||||||
clientsName.push(userContact.data.name);
|
|
||||||
clients.push(userContact.data.phone);
|
|
||||||
}
|
|
||||||
|
|
||||||
const destinationFk = String(clientsFk);
|
|
||||||
const destination = String(clients);
|
|
||||||
|
|
||||||
this.newSMS = Object.assign({
|
|
||||||
destinationFk: destinationFk,
|
|
||||||
destination: destination
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$.sms.open();
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
|
||||||
this.vnApp.showError(this.$t(e.message));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnRouteTickets', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
require: {
|
|
||||||
card: '^vnRouteCard'
|
|
||||||
},
|
|
||||||
bindings: {
|
|
||||||
route: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,277 +0,0 @@
|
||||||
/* eslint max-len: ["error", { "code": 150 }]*/
|
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('Route', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
let $scope;
|
|
||||||
|
|
||||||
beforeEach(ngModule('route'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
const $element = angular.element('<vn-route-tickets></vn-route-tickets>');
|
|
||||||
controller = $componentController('vnRouteTickets', {$element, $scope});
|
|
||||||
controller.route = {id: 1};
|
|
||||||
controller.$.model = {
|
|
||||||
refresh: () => {},
|
|
||||||
remove: () => {}
|
|
||||||
};
|
|
||||||
controller.card = {reload: () => {}};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('route setter/getter', () => {
|
|
||||||
it('should return the route id', () => {
|
|
||||||
controller.route = 2;
|
|
||||||
|
|
||||||
expect(controller.route).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('isChecked getter', () => {
|
|
||||||
it('should return false if none of the tickets is checked or there are no tickets', () => {
|
|
||||||
expect(controller.isChecked).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return true if any of the tickets is checked', () => {
|
|
||||||
controller.tickets = [{checked: true}];
|
|
||||||
|
|
||||||
expect(controller.isChecked).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getHighestPriority()', () => {
|
|
||||||
it('should return the highest value found in priorities plus 1', () => {
|
|
||||||
controller.$.model = {data: [
|
|
||||||
{priority: 99},
|
|
||||||
{priority: 1},
|
|
||||||
{priority: 2},
|
|
||||||
{priority: 3},
|
|
||||||
{priority: 4},
|
|
||||||
{priority: 5},
|
|
||||||
]};
|
|
||||||
|
|
||||||
let result = controller.getHighestPriority();
|
|
||||||
|
|
||||||
expect(result).toEqual(100);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setHighestPriority()', () => {
|
|
||||||
it('should set a ticket highest priority', () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
controller.$.model.data = [{priority: 3}];
|
|
||||||
const ticket = {id: 1, priority: 2};
|
|
||||||
const res = {data: {priority: 4}};
|
|
||||||
|
|
||||||
$httpBackend.expectPATCH(`Tickets/${ticket.id}/`).respond(res);
|
|
||||||
controller.setHighestPriority(ticket);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setPriority()', () => {
|
|
||||||
it('should set a ticket priority', () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
const ticketId = 1;
|
|
||||||
const priority = 999;
|
|
||||||
|
|
||||||
$httpBackend.expectPATCH(`Tickets/${ticketId}/`).respond('ok');
|
|
||||||
controller.setPriority(ticketId, priority);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('deletePriority()', () => {
|
|
||||||
it('should delete priority of all tickets', () => {
|
|
||||||
jest.spyOn(controller.$.model, 'refresh');
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
controller.tickets = [{id: 1, checked: true}];
|
|
||||||
|
|
||||||
$httpBackend.expectPATCH(`Tickets/${controller.tickets[0].id}/`).respond();
|
|
||||||
controller.deletePriority();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setOrderedPriority()', () => {
|
|
||||||
it('should set priority of all tickets starting by 1', () => {
|
|
||||||
jest.spyOn(controller.$.model, 'refresh');
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
const tickets = [{id: 1, checked: true}];
|
|
||||||
|
|
||||||
$httpBackend.expectPATCH(`Tickets/${tickets[0].id}/`).respond();
|
|
||||||
controller.setOrderedPriority(tickets);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getSelectedItems()', () => {
|
|
||||||
it('should return the selected items', () => {
|
|
||||||
let items = [
|
|
||||||
{id: 1, checked: true},
|
|
||||||
{id: 2, checked: false},
|
|
||||||
{id: 3, checked: true},
|
|
||||||
{id: 4, checked: false},
|
|
||||||
{id: 5, checked: true},
|
|
||||||
];
|
|
||||||
|
|
||||||
let selectedItems = controller.getSelectedItems(items);
|
|
||||||
|
|
||||||
expect(selectedItems).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('goToBuscaman()', () => {
|
|
||||||
it('should open buscaman with the given arguments', () => {
|
|
||||||
jest.spyOn(window, 'open').mockReturnThis();
|
|
||||||
const expectedUrl = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=46460%20Av%20Espioca%20100+to:n19%20London%20my%20street';
|
|
||||||
controller.route = {vehicleFk: 1};
|
|
||||||
const url = `Routes/${controller.route.vehicleFk}/getDeliveryPoint`;
|
|
||||||
$httpBackend.expectGET(url).respond('46460 Av Espioca 100');
|
|
||||||
|
|
||||||
controller.tickets = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
checked: true,
|
|
||||||
street: 'my street',
|
|
||||||
postalCode: 'n19',
|
|
||||||
city: 'London'
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
controller.goToBuscaman();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(window.open).toHaveBeenCalledWith(expectedUrl, '_blank');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('showDeleteConfirm()', () => {
|
|
||||||
it('should open a confirm dialog after setting the selected ticket into the controller', () => {
|
|
||||||
controller.$.confirm = {show: () => {}};
|
|
||||||
jest.spyOn(controller.$.confirm, 'show');
|
|
||||||
let ticketId = 1;
|
|
||||||
|
|
||||||
controller.showDeleteConfirm(ticketId);
|
|
||||||
|
|
||||||
expect(controller.selectedTicket).toEqual(ticketId);
|
|
||||||
expect(controller.$.confirm.show).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('removeTicketFromRoute()', () => {
|
|
||||||
it('should perform a patch query then call showSuccess and updateVolume methods', () => {
|
|
||||||
controller.$params = {id: 1101};
|
|
||||||
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
jest.spyOn(controller.$.model, 'remove');
|
|
||||||
|
|
||||||
let ticketId = 1;
|
|
||||||
controller.selectedTicket = ticketId;
|
|
||||||
|
|
||||||
$httpBackend.whenPOST(`Routes/${controller.$params.id}/updateVolume`).respond(200);
|
|
||||||
$httpBackend.expectPATCH(`Tickets/${ticketId}/`).respond('ok');
|
|
||||||
controller.removeTicketFromRoute();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Ticket removed from route');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('updateVolume()', () => {
|
|
||||||
it('should perform a POST query then call both reload and refresh methods', () => {
|
|
||||||
controller.$params = {id: 999};
|
|
||||||
jest.spyOn(controller.$.model, 'refresh');
|
|
||||||
jest.spyOn(controller.card, 'reload');
|
|
||||||
|
|
||||||
let ticketId = 1;
|
|
||||||
controller.selectedTicket = ticketId;
|
|
||||||
|
|
||||||
const url = `Routes/${controller.$params.id}/updateVolume`;
|
|
||||||
$httpBackend.expectPOST(url).respond('ok');
|
|
||||||
controller.updateVolume();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
|
||||||
expect(controller.card.reload).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onDrop()', () => {
|
|
||||||
it('should call the insert method when dragging a ticket number', () => {
|
|
||||||
jest.spyOn(controller, 'insert');
|
|
||||||
|
|
||||||
const expectedTicketId = '11';
|
|
||||||
const draggedElement = '11';
|
|
||||||
const $event = {
|
|
||||||
dataTransfer: {
|
|
||||||
getData: () => draggedElement
|
|
||||||
}
|
|
||||||
};
|
|
||||||
controller.onDrop($event);
|
|
||||||
|
|
||||||
expect(controller.insert).toHaveBeenCalledWith(expectedTicketId);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the insert method when dragging a ticket link', () => {
|
|
||||||
jest.spyOn(controller, 'insert');
|
|
||||||
|
|
||||||
const expectedTicketId = '11';
|
|
||||||
const draggedElement = 'http://arkamcity.com/#!/ticket/11/summary';
|
|
||||||
const $event = {
|
|
||||||
dataTransfer: {
|
|
||||||
getData: () => draggedElement
|
|
||||||
}
|
|
||||||
};
|
|
||||||
controller.onDrop($event);
|
|
||||||
|
|
||||||
expect(controller.insert).toHaveBeenCalledWith(expectedTicketId);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error when dragging an invalid ticket link', () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showError');
|
|
||||||
|
|
||||||
const draggedElement = 'http://arkamcity.com/#!/item/11/summary';
|
|
||||||
const $event = {
|
|
||||||
dataTransfer: {
|
|
||||||
getData: () => draggedElement
|
|
||||||
}
|
|
||||||
};
|
|
||||||
controller.onDrop($event);
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith('Ticket not found');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('insert()', () => {
|
|
||||||
it('should make a HTTP patch query and then call both refresh and showSuccess methods', () => {
|
|
||||||
controller.$params = {id: 1101};
|
|
||||||
|
|
||||||
jest.spyOn(controller.$.model, 'refresh').mockReturnThis();
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
|
|
||||||
const ticketId = 11;
|
|
||||||
const data = {ticketId};
|
|
||||||
|
|
||||||
$httpBackend.whenPOST(`Routes/${controller.$params.id}/updateVolume`).respond(200);
|
|
||||||
$httpBackend.expect('PATCH', `Routes/1/insertTicket`, data).respond();
|
|
||||||
controller.insert(ticketId);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
|
||||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,18 +0,0 @@
|
||||||
Remove ticket: Eliminar ticket
|
|
||||||
Open buscaman: Abrir buscaman
|
|
||||||
Ticket removed from route: Ticket quitado de la ruta
|
|
||||||
Order changed: Orden cambiado
|
|
||||||
Delete ticket from route?: ¿Quitar el ticket de la ruta?
|
|
||||||
Sort routes: Ordenar rutas
|
|
||||||
Add ticket: Añadir ticket
|
|
||||||
Tickets to add: Tickets a añadir
|
|
||||||
Ticket not found: No se ha encontrado el ticket
|
|
||||||
The selected ticket is not suitable for this route: El ticket seleccionado no es apto para esta ruta
|
|
||||||
PC: CP
|
|
||||||
The route's vehicle doesn't have a delivery point: El vehículo de la ruta no tiene un punto de entrega
|
|
||||||
The route doesn't have a vehicle: La ruta no tiene un vehículo
|
|
||||||
Population: Población
|
|
||||||
Unlink selected zone?: Desvincular zona seleccionada?
|
|
||||||
Delete priority: Borrar orden
|
|
||||||
Renumber all tickets in the order you see on the screen: Renumerar todos los tickets con el orden que ves por pantalla
|
|
||||||
Assign highest priority: Asignar máxima prioridad
|
|
|
@ -1,16 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
vn-route-tickets form{
|
|
||||||
margin: 0 auto;
|
|
||||||
max-width: $width-lg;
|
|
||||||
|
|
||||||
.order-field {
|
|
||||||
max-width: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-right{
|
|
||||||
display: block;
|
|
||||||
padding-right: 50px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
Loading…
Reference in New Issue