This commit is contained in:
parent
5567359d73
commit
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';
|
||||
|
||||
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';
|
||||
|
||||
export default class Route extends ModuleMain {
|
||||
$postLink() {
|
||||
const to = Date.vnNew();
|
||||
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);
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
}
|
||||
|
||||
fetchParams($params) {
|
||||
const hasEntries = Object.entries($params).length;
|
||||
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;
|
||||
async $onInit() {
|
||||
this.$state.go('home');
|
||||
window.location.href = await this.vnApp.getUrl(`route/`);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnRoute', {
|
||||
controller: Route,
|
||||
controller: Entry,
|
||||
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"],
|
||||
"menus": {
|
||||
"main": [
|
||||
{"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"}
|
||||
{"state": "route.index", "icon": "icon-delivery"}
|
||||
]
|
||||
},
|
||||
"routes": [
|
||||
|
@ -33,108 +22,6 @@
|
|||
"state": "route.index",
|
||||
"component": "vn-route-index",
|
||||
"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