added zone index & zone create

This commit is contained in:
Joan Sanchez 2018-09-19 15:05:07 +02:00
parent fd08bb96dd
commit d5ca385ccd
42 changed files with 899 additions and 48 deletions

View File

@ -49,6 +49,9 @@
</vn-td> </vn-td>
</vn-tr> </vn-tr>
</vn-tbody> </vn-tbody>
<vn-empty-rows ng-if="model.data.length === 0" translate>
No results
</vn-empty-rows>
</vn-table> </vn-table>
</vn-card> </vn-card>
<vn-pagination <vn-pagination

View File

@ -41,3 +41,4 @@ import './th';
import './input-range'; import './input-range';
import './chip'; import './chip';
import './input-number'; import './input-number';
import './input-time';

View File

@ -45,7 +45,7 @@ export default class InputNumber extends Textfield {
} }
get step() { get step() {
return parseInt(this.input.step); return parseFloat(this.input.step);
} }
set step(value) { set step(value) {

View File

@ -0,0 +1,37 @@
<div class="container"
ng-class="{selected: $ctrl.hasFocus}">
<div class="textField">
<div class="leftIcons" ng-transclude="leftIcons"></div>
<div class="infix">
<input
class="mdl-textfield__input"
type="time"
ng-model="$ctrl.value"
vn-validation="{{$ctrl.rule}}"
ng-disabled="$ctrl.disabled"
ng-readonly="$ctrl.readonly"
ng-focus="$ctrl.hasFocus = true"
ng-blur="$ctrl.hasFocus = false"
tabindex="{{$ctrl.input.tabindex}}"/>
<label class="label" translate>{{::$ctrl.label}}</label>
</div>
<div class="underline"></div>
<div class="selected underline"></div>
<div class="suffix">
<i class="material-icons clear"
translate-attr="{title: 'Clear'}"
ng-show="!$ctrl.disabled
&& $ctrl.hasValue
&& !$ctrl.unclearable"
ng-click="$ctrl.clear()">
clear
</i>
<i class="material-icons"
ng-if="$ctrl.hasInfo"
vn-tooltip="{{$ctrl.info}}">
info_outline
</i>
</div>
<div class="rightIcons" ng-transclude="rightIcons"></div>
</div>
</div>

View File

@ -0,0 +1,55 @@
import ngModule from '../../module';
import Textfield from '../textfield/textfield';
import './style.scss';
export default class InputTime extends Textfield {
constructor($element, $scope, $attrs, vnTemplate, $transclude, $filter) {
super($element, $scope, $attrs, vnTemplate, $transclude);
this.$filter = $filter;
}
get value() {
return this._value;
}
set value(value) {
this._value = value;
this.hasValue = this._value !== null;
if (this.hasValue) this.element.classList.add('not-empty');
this.element.querySelector('.infix').classList.remove('invalid', 'validated');
}
get step() {
return parseFloat(this.input.step);
}
set step(value) {
this.input.step = value;
}
}
InputTime.$inject = ['$element', '$scope', '$attrs', 'vnTemplate', '$transclude', '$filter'];
ngModule.component('vnInputTime', {
template: require('./index.html'),
controller: InputTime,
transclude: {
leftIcons: '?tLeftIcons',
rightIcons: '?tRightIcons'
},
bindings: {
label: '@?',
disabled: '<?',
readonly: '<?',
step: '<?',
rule: '@?',
value: '=model',
vnTabIndex: '@?',
onChange: '&',
onClear: '&'
}
});

View File

@ -0,0 +1,60 @@
import './index.js';
describe('Component vnInputNumber', () => {
let $componentController;
let $scope;
let $attrs;
let $timeout;
let $element;
let controller;
beforeEach(() => {
angular.mock.module('claim');
});
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => {
$componentController = _$componentController_;
$scope = $rootScope.$new();
$attrs = {};
$timeout = _$timeout_;
$element = angular.element('<div><input><div class="infix invalid validated"><div class="rightIcons"></div></div>');
controller = $componentController('vnInputNumber', {$element, $scope, $attrs, $timeout, $transclude: () => {}});
}));
describe('value() setter', () => {
it(`should set _value to a given value, add the class not-empty and remove invalid and validated`, () => {
controller.value = 'pepino';
let classes = controller.element.classList.toString();
expect(classes).toContain('not-empty');
expect(controller._value).toEqual('pepino');
classes = controller.element.querySelector('.infix').classList.toString();
expect(classes).not.toContain('invalid validated');
});
it(`should set _value to a given value and not add the class not-empty if the given value is null`, () => {
controller.value = null;
let classes = controller.element.classList.toString();
expect(classes).not.toContain('not-empty');
expect(controller._value).toEqual(null);
});
});
describe('step() setter/getter', () => {
it(`should set input.step to a given value`, () => {
controller.step = 50;
expect(controller.input.step).toEqual('50');
});
it(`should return a number`, () => {
controller.step = 50;
expect(controller.step).toEqual(50);
expect(typeof controller.step).toEqual('number');
});
});
});

View File

@ -0,0 +1,12 @@
@import 'colors';
@import '../textfield/style.scss';
vn-input-time {
@extend vn-textfield;
input[type="time"] {
clip-path: inset(0 17px 0 0);
outline:none;
outline:0;
}
}

View File

@ -26,7 +26,6 @@ vn-textfield {
} }
} }
.infix { .infix {
position: relative;
display: block; display: block;
flex: auto; flex: auto;
width: 100%; width: 100%;
@ -49,6 +48,7 @@ vn-textfield {
label { label {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0;
padding: 4px 0!important; padding: 4px 0!important;
pointer-events: none; pointer-events: none;
color: $secondary-font-color; color: $secondary-font-color;

View File

@ -7,5 +7,6 @@ module.exports.watcher = {
check: () => {}, check: () => {},
notifySaved: () => {}, notifySaved: () => {},
setDirty: () => {}, setDirty: () => {},
setPristine: () => {} setPristine: () => {},
updateOriginalData: () => {}
}; };

View File

@ -6,3 +6,4 @@ salix: []
ticket: [item, client] ticket: [item, client]
order: [item, ticket] order: [item, ticket]
claim: [item, client] claim: [item, client]
route: []

View File

@ -4,19 +4,57 @@
"icon" : "local_shipping", "icon" : "local_shipping",
"validations" : true, "validations" : true,
"routes": [ "routes": [
{ /* {
"url": "/routes", "url": "/route",
"state": "routes", "state": "route",
"abstract": true, "abstract": true,
"component": "ui-view", "component": "ui-view",
"description": "Routes" "description": "Routes"
}, },
{ {
"url": "/index?q", "url": "/index?q",
"state": "routes.index", "state": "route.index",
"component": "vn-route-index", "component": "vn-route-index",
"description": "List", "description": "List",
"acl": ["developer"] "acl": ["developer"]
}, */
{
"url": "/zone",
"state": "zone",
"abstract": true,
"component": "ui-view",
"description": "Zones"
},
{
"url": "/index?q",
"state": "zone.index",
"component": "vn-zone-index",
"description": "List",
"acl": ["developer"]
},
{
"url": "/create",
"state": "zone.create",
"component": "vn-zone-create",
"description": "New zone"
},
{
"url": "/:id",
"state": "zone.card",
"abstract": true,
"component": "vn-zone-card"
},
{
"url": "/basic-data",
"state": "zone.card.basicData",
"component": "vn-zone-basic-data",
"description": "Basic data",
"params": {
"client": "$ctrl.client"
},
"menu": {
"icon": "settings"
}
} }
] ]
} }

View File

@ -1,3 +1,8 @@
export * from './module'; export * from './module';
// import components // import components
import './zone/card';
import './zone/descriptor';
import './zone/search-panel';
import './zone/index';
import './zone/create';

View File

@ -1,15 +1,11 @@
Basic data: Datos básicos Name: Nombre
Logistic data: Datos logísticos
Assigned tickets: Tickets asignados
Routes: Rutas
Route: Ruta
Date: Fecha
Agency: Agencia Agency: Agencia
Driver: Conductor Warehouse: Almacén
Vehicle: Vehículo Hour: Hora (ETD)
Start Hour: Hora Inicio Price: Precio
End Hour: Hora Fin Create: Crear
Start Km: Km Inicio
End Km: Km Fin Zones: Zonas
Packages: Bultos List: Listado
Route document: Documento de Ruta New zone: Nueva zona
Basic data: Datos básicos

View File

@ -1,5 +1,5 @@
import {ng} from 'vendor'; import {ng} from 'vendor';
import 'core'; import 'core';
const ngModule = ng.module('route', []); const ngModule = ng.module('route', ['vnCore']);
export default ngModule; export default ngModule;

View File

@ -0,0 +1,11 @@
<vn-main-block>
<vn-horizontal>
<vn-auto class="left-block">
<vn-zone-descriptor order="$ctrl.zone"></vn-zone-descriptor>
<vn-left-menu></vn-left-menu>
</vn-auto>
<vn-one>
<vn-vertical margin-medium ui-view></vn-vertical>
</vn-one>
</vn-horizontal>
</vn-main-block>

View File

@ -0,0 +1,60 @@
import ngModule from '../../module';
class Controller {
constructor($http, $state) {
this.$http = $http;
this.$state = $state;
this.order = {};
this.filter = {
include: [
{relation: 'agencyMode', scope: {fields: ['name']}},
{relation: 'address', scope: {fields: ['nickname']}},
{relation: 'rows', scope: {fields: ['id']}},
{
relation: 'client',
scope: {
fields: ['salesPersonFk', 'name', 'isActive', 'isFreezed', 'isTaxDataChecked'],
include: {
relation: 'salesPerson',
fields: ['firstName', 'name']
}
}
}
]
};
}
/* getOrder() {
let json = encodeURIComponent(JSON.stringify(this.filter));
let query = `/order/api/Orders/${this.$state.params.id}?filter=${json}`;
this.$http.get(query).then(res => {
if (res.data) {
this.order = res.data;
this.getTotal();
}
});
}
getTotal() {
let query = `/order/api/Orders/${this.$state.params.id}/getTotal`;
this.$http.get(query).then(res => {
if (res.data) {
this.order.total = res.data.total;
}
});
}
$onInit() {
this.getOrder();
}
reload() {
this.getOrder();
} */
}
Controller.$inject = ['$http', '$state'];
ngModule.component('vnZoneCard', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,68 @@
import './index.js';
describe('Order', () => {
describe('Component vnOrderCard', () => {
let $componentController;
let $scope;
let controller;
let $httpBackend;
let $state;
beforeEach(() => {
angular.mock.module('order');
});
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
$componentController = _$componentController_;
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
$scope = $rootScope.$new();
$scope.card = {createOrder: () => {}};
$state = {params: {id: 1}};
controller = $componentController('vnOrderCard', {$scope: $scope, $state: $state});
}));
describe('getOrder()', () => {
it(`should make a query, save the data in order and call get order if the response has data`, () => {
spyOn(controller, 'getTotal');
let json = encodeURIComponent(JSON.stringify(controller.filter));
$httpBackend.expectGET(`/order/api/Orders/${controller.$state.params.id}?filter=${json}`).respond({id: 1});
controller.getOrder();
$httpBackend.flush();
expect(controller.order).toEqual({id: 1});
expect(controller.getTotal).toHaveBeenCalledWith();
});
it(`should make a query and not call getTotal if the response is not defined`, () => {
spyOn(controller, 'getTotal');
let json = encodeURIComponent(JSON.stringify(controller.filter));
$httpBackend.expectGET(`/order/api/Orders/${controller.$state.params.id}?filter=${json}`).respond(undefined);
controller.getOrder();
$httpBackend.flush();
expect(controller.order).toEqual({});
expect(controller.getTotal).not.toHaveBeenCalledWith();
});
});
describe('getTotal()', () => {
it(`should make a query and save the data in order.total`, () => {
$httpBackend.expectGET(`/order/api/Orders/${controller.$state.params.id}/getTotal`).respond({total: '20M'});
controller.getTotal();
$httpBackend.flush();
expect(controller.order.total).toEqual('20M');
});
it(`should make a query and not save the respones if is not defined`, () => {
$httpBackend.expectGET(`/order/api/Orders/${controller.$state.params.id}/getTotal`).respond();
controller.getTotal();
$httpBackend.flush();
expect(controller.order.total).toEqual(undefined);
});
});
});
});

View File

@ -0,0 +1,69 @@
<vn-watcher
vn-id="watcher"
data="$ctrl.zone"
form="form">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium>
<div style="max-width: 50em; margin: 0 auto;">
<vn-card pad-large>
<vn-title>New zone</vn-title>
<vn-horizontal>
<vn-textfield vn-two vn-focus
label="Name"
field="$ctrl.zone.name">
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
vn-one
field="$ctrl.zone.warehouseFk"
url="/route/api/Warehouses"
show-field="name"
value-field="id"
label="Warehouse">
</vn-autocomplete>
<vn-autocomplete
vn-one
field="$ctrl.zone.agencyModeFk"
url="/route/api/AgencyModes"
show-field="name"
value-field="id"
label="Agency">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-input-number
vn-two
min="0"
value="$ctrl.zone.travelingDays"
step="1"
label="Traveling days"
field="$ctrl.zone.travelingDays">
</vn-input-number>
<vn-input-time
vn-two
label="Estimated hour (ETD)"
field="$ctrl.zone.hour">
</vn-input-time>
</vn-horizontal>
<vn-horizontal>
<vn-input-number vn-one
label="Price"
field="$ctrl.zone.price"
min="0.00"
step="0.50">
</vn-input-number>
<vn-input-number vn-one
label="Bonus"
field="$ctrl.zone.bonus"
min="0.00"
step="0.50">
</vn-input-number>
</vn-horizontal>
</vn-card>
<vn-button-bar>
<vn-submit label="Create"></vn-submit>
<vn-button ui-sref="zone.index" label="Cancel"></vn-button>
</vn-button-bar>
</div>
</form>

View File

@ -0,0 +1,34 @@
import ngModule from '../../module';
export default class Controller {
constructor($scope, $state, $http) {
this.$scope = $scope;
this.$state = $state;
this.$http = $http;
this.zone = {
travelingDays: 0,
price: 0.50,
bonus: 0.50
};
}
onSubmit() {
this.$scope.watcher.check();
let data = Object.assign({}, this.zone);
data.hour = new Date(this.zone.hour);
this.$http.post('/route/api/Zones', data).then(res => {
this.$scope.watcher.updateOriginalData();
this.$scope.watcher.setPristine();
this.$scope.watcher.notifySaved();
this.$state.go('zone.card.basicData', {id: res.data.id});
});
}
}
Controller.$inject = ['$scope', '$state', '$http'];
ngModule.component('vnZoneCreate', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,43 @@
import './index';
import {watcher} from '../../../../helpers/watcherHelper';
describe('Route', () => {
describe('Component vnZoneCreate', () => {
let $componentController;
let $httpBackend;
let $scope;
let $state;
let controller;
beforeEach(() => {
angular.mock.module('route');
});
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$state_) => {
$componentController = _$componentController_;
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
$httpBackend.when('GET', 'claim/api/Claims/ClaimBeginnings').respond({});
$scope = $rootScope.$new();
$state = _$state_;
$scope.watcher = watcher;
controller = $componentController('vnZoneCreate', {$scope: $scope});
}));
describe('onSubmit()', () => {
it(`should call submit() on the watcher then expect a callback`, () => {
spyOn($state, 'go');
controller.zone = {
name: 'Zone One'
};
$httpBackend.expectPOST(`/route/api/Zones`).respond({id: 1234});
controller.onSubmit();
$httpBackend.flush();
expect(controller.$state.go).toHaveBeenCalledWith('zone.card.basicData', {id: 1234});
});
});
});
});

View File

@ -0,0 +1,3 @@
Traveling days: Días de viaje
Estimated hour (ETD): Hora estimada (ETD)
Bonus: Bonificación

View File

@ -0,0 +1,19 @@
<vn-card margin-medium-v class="vn-descriptor">
<vn-horizontal class="header">
<a translate-attr="{title: 'Return to module index'}" ui-sref="zone.index">
<vn-icon icon="chevron_left"></vn-icon>
</a>
<vn-icon icon="my_location"></vn-icon>
<a translate-attr="{title: 'Preview'}" ui-sref="order.card.summary">
<vn-icon icon="desktop_windows"></vn-icon>
</a>
</vn-horizontal>
<div pad-medium>
<vn-label-value label="ID"
value="{{$ctrl.zone.id}}">
</vn-label-value>
<vn-label-value label="Client"
value="{{$ctrl.order.client.name}}">
</vn-label-value>
</div>
</vn-card>

View File

@ -0,0 +1,18 @@
import ngModule from '../../module';
import './style.scss';
class Controller {
constructor($translate) {
this.translate = $translate;
}
}
Controller.$inject = ['$translate'];
ngModule.component('vnZoneDescriptor', {
template: require('./index.html'),
bindings: {
order: '<'
},
controller: Controller
});

View File

@ -0,0 +1,8 @@
Client: Cliente
Confirmed: Confirmado
Not confirmed: Sin confirmar
State: Estado
Landed: F. entrega
Items: Articulos
Agency: Agencia
Sales person: Comercial

View File

@ -0,0 +1,5 @@
vn-label-value[label=Total]{
padding-top: 10px;
display: block;
font-size: 1.2em;
}

View File

@ -0,0 +1,55 @@
<vn-crud-model
vn-id="model"
url="/route/api/Zones"
filter="::$ctrl.filter"
limit="20"
data="zones"
auto-load="false">
</vn-crud-model>
<div margin-medium>
<div class="vn-list">
<vn-card pad-medium-h>
<vn-searchbar
panel="vn-zone-search-panel"
model="model"
expr-builder="$ctrl.exprBuilder(param, value)"
vn-focus>
</vn-searchbar>
</vn-card>
</div>
<vn-card margin-medium-v pad-medium>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="id" number>Id</vn-th>
<vn-th field="name">Name</vn-th>
<vn-th field="agencyModeFk">Agency</vn-th>
<vn-th field="warehouseFK">Warehouse</vn-th>
<vn-th field="hour">Hour</vn-th>
<vn-th field="price">Price</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="zone in zones" ui-sref="zone.card.basicData({id: zone.id})" class=clickable>
<vn-td number>{{::zone.id}}</vn-td>
<vn-td>{{::zone.name}}</vn-td>
<vn-td>{{::zone.agencyMode.name}}</vn-td>
<vn-td>{{::zone.warehouse.name}}</vn-td>
<vn-td>{{::zone.hour | date: 'HH:mm'}}</vn-td>
<vn-td number>{{::zone.price | currency:'€':2}}</vn-td>
</vn-tr>
</vn-tbody>
<vn-empty-rows ng-if="model.data.length === 0" translate>
No results
</vn-empty-rows>
</vn-table>
</vn-card>
<vn-pagination
model="model"
scroll-selector="ui-view">
</vn-pagination>
</div>
<a ui-sref="zone.create" vn-tooltip="New zone" vn-bind="+" fixed-bottom-right>
<vn-float-button icon="add_location"></vn-float-button>
</a>

View File

@ -0,0 +1,32 @@
import ngModule from '../../module';
export default class Controller {
constructor($scope) {
this.$scope = $scope;
this.filter = {
include: [
{relation: 'agencyMode', fields: ['name']},
{relation: 'warehouse', fields: ['name']}
]
};
}
exprBuilder(param, value) {
switch (param) {
case 'search':
return /^\d+$/.test(value)
? {id: value}
: {name: {regexp: value}};
case 'warehouseFk':
case 'agencyModeFk':
return {[param]: value};
}
}
}
Controller.$inject = ['$scope'];
ngModule.component('vnZoneIndex', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,43 @@
import './index.js';
describe('Route', () => {
describe('Component vnZoneIndex', () => {
let $componentController;
let controller;
beforeEach(() => {
angular.mock.module('route');
});
beforeEach(angular.mock.inject(_$componentController_ => {
$componentController = _$componentController_;
controller = $componentController('vnZoneIndex');
}));
describe('exprBuilder()', () => {
it('should return a formated object with the id in case of search', () => {
let param = 'search';
let value = 1;
let result = controller.exprBuilder(param, value);
expect(result).toEqual({id: 1});
});
it('should return a formated object with the warehouseFk in case of warehouseFk', () => {
let param = 'warehouseFk';
let value = 'Silla';
let result = controller.exprBuilder(param, value);
expect(result).toEqual({warehouseFk: 'Silla'});
});
it('should return a formated object with the warehouseFk in case of warehouseFk', () => {
let param = 'agencyModeFk';
let value = 'My Delivery';
let result = controller.exprBuilder(param, value);
expect(result).toEqual({agencyModeFk: 'My Delivery'});
});
});
});
});

View File

@ -0,0 +1,33 @@
<div pad-large style="min-width: 30em">
<form ng-submit="$ctrl.onSearch()">
<vn-horizontal>
<vn-textfield
vn-one
label="Name"
model="filter.name"
vn-focus>
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
vn-one
label="Agency"
field="filter.agencyModeFk"
url="/route/api/AgencyModes"
show-field="name"
value-field="id">
</vn-autocomplete>
<vn-autocomplete
vn-one
label="Warehouse"
field="filter.warehouseFk"
url="/route/api/Warehouses"
show-field="name"
value-field="id">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal margin-large-top>
<vn-submit label="Search"></vn-submit>
</vn-horizontal>
</form>
</div>

View File

@ -0,0 +1,7 @@
import ngModule from '../../module';
import SearchPanel from 'core/src/components/searchbar/search-panel';
ngModule.component('vnZoneSearchPanel', {
template: require('./index.html'),
controller: SearchPanel
});

View File

@ -75,6 +75,9 @@
</vn-td> </vn-td>
</a> </a>
</vn-tbody> </vn-tbody>
<vn-empty-rows ng-if="model.data.length === 0" translate>
No results
</vn-empty-rows>
</vn-table> </vn-table>
</vn-card> </vn-card>
<vn-pagination <vn-pagination

View File

@ -87,7 +87,7 @@ describe('Ticket Create packages path', () => {
.click(selectors.ticketPackages.savePackagesButton) .click(selectors.ticketPackages.savePackagesButton)
.waitForLastSnackbar() .waitForLastSnackbar()
.then(result => { .then(result => {
expect(result).toEqual('The package cannot be blank'); expect(result).toEqual('Package cannot be blank');
}); });
}); });

View File

@ -0,0 +1,8 @@
ALTER TABLE `vn`.`zoneGeo`
RENAME TO `vn`.`zoneIncluded` ;
ALTER TABLE `vn`.`zoneNest`
RENAME TO `vn`.`zoneGeo` ;
ALTER TABLE `vn`.`zone`
CHANGE COLUMN `agencyFk` `agencyModeFk` INT(11) NOT NULL ;

View File

@ -11,7 +11,7 @@
"Is invalid": "Is invalid", "Is invalid": "Is invalid",
"Quantity cannot be zero": "La cantidad no puede ser cero", "Quantity cannot be zero": "La cantidad no puede ser cero",
"Enter an integer different to zero": "Introduce un entero distinto de cero", "Enter an integer different to zero": "Introduce un entero distinto de cero",
"The package cannot be blank": "El embalaje no puede estar en blanco", "Package cannot be blank": "El embalaje no puede estar en blanco",
"The company name must be unique": "La razón social debe ser única", "The company name must be unique": "La razón social debe ser única",
"Invalid email": "Correo electrónico inválido", "Invalid email": "Correo electrónico inválido",
"The IBAN does not have the correct format": "El IBAN no tiene el formato correcto", "The IBAN does not have the correct format": "El IBAN no tiene el formato correcto",
@ -48,5 +48,7 @@
"The tag can't be repeated": "El tag no puede repetirse", "The tag can't be repeated": "El tag no puede repetirse",
"The observation type can't be repeated": "El tipo de observación no puede repetirse", "The observation type can't be repeated": "El tipo de observación no puede repetirse",
"A claim with that sale already exists": "Ya existe una reclamación para esta línea", "A claim with that sale already exists": "Ya existe una reclamación para esta línea",
"You don't have enough privileges to change that field": "You don't have enough privileges to change that field" "You don't have enough privileges to change that field": "You don't have enough privileges to change that field",
"Warehouse cannot be blank": "El almacén no puede quedar en blanco",
"Agency cannot be blank": "La agencia no puede quedar en blanco"
} }

View File

@ -0,0 +1,25 @@
{
"name": "ZoneCalendar",
"base": "VnModel",
"options": {
"mysql": {
"table": "ZoneCalendar"
}
},
"properties": {
"zoneFk": {
"id": true,
"type": "Number"
},
"delivered": {
"type": "Date"
}
},
"relations": {
"zone": {
"type": "belongsTo",
"model": "Zone",
"foreignKey": "zoneFk"
}
}
}

View File

@ -0,0 +1,24 @@
{
"name": "ZoneGeo",
"base": "VnModel",
"options": {
"mysql": {
"table": "zoneGeo"
}
},
"properties": {
"id": {
"id": true,
"type": "Number"
},
"name": {
"type": "String"
},
"lft": {
"type": "Number"
},
"rgt": {
"type": "Number"
}
}
}

View File

@ -0,0 +1,30 @@
{
"name": "ZoneIncluded",
"base": "VnModel",
"options": {
"mysql": {
"table": "zoneIncluded"
}
},
"properties": {
"zoneFk": {
"id": true,
"type": "Number"
},
"isIncluded": {
"type": "Boolean"
}
},
"relations": {
"zone": {
"type": "belongsTo",
"model": "Zone",
"foreignKey": "zoneFk"
},
"geo": {
"type": "belongsTo",
"model": "ZoneGeo",
"foreignKey": "geoFk"
}
}
}

View File

@ -0,0 +1,9 @@
module.exports = Self => {
Self.validatesPresenceOf('warehouseFk', {
message: `Warehouse cannot be blank`
});
Self.validatesPresenceOf('agencyModeFk', {
message: `Agency cannot be blank`
});
};

View File

@ -1,23 +1,47 @@
{ {
"name": "Zone", "name": "Zone",
"base": "VnModel", "base": "VnModel",
"options": { "options": {
"mysql": { "mysql": {
"table": "zone" "table": "zone"
} }
}, },
"properties": { "properties": {
"id": { "id": {
"id": true, "id": true,
"type": "Number", "type": "Number"
"forceId": false },
}, "name": {
"name": { "type": "String",
"type": "String" "required": true
}, },
"printingOrder":{ "hour": {
"type": "Number" "type": "Date",
} "required": true
},
"travelingDays": {
"type": "Number",
"required": true
},
"price": {
"type": "Number",
"required": true
},
"bonus": {
"type": "Number",
"required": true
}
},
"relations": {
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
},
"agencyMode": {
"type": "belongsTo",
"model": "AgencyMode",
"foreignKey": "agencyModeFk"
}
} }
} }

View File

@ -7,5 +7,14 @@
}, },
"Zone": { "Zone": {
"dataSource": "vn" "dataSource": "vn"
},
"ZoneGeo": {
"dataSource": "vn"
},
"ZoneCalendar": {
"dataSource": "vn"
},
"ZoneIncluded": {
"dataSource": "vn"
} }
} }

View File

@ -2,7 +2,7 @@
<html ng-app="salix"> <html ng-app="salix">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title vn-title translate>Salix</title> <title vn-title translate></title>
<script src="/acl"></script> <script src="/acl"></script>
</head> </head>
<body> <body>

View File

@ -9,5 +9,5 @@ module.exports = function(Self) {
return !isNaN(quantity) && quantity != 0; return !isNaN(quantity) && quantity != 0;
} }
Self.validatesPresenceOf('packagingFk', {message: 'The package cannot be blank'}); Self.validatesPresenceOf('packagingFk', {message: 'Package cannot be blank'});
}; };