-
- {{::travel.id}}
{{::travel.ref}}
{{::travel.agencyModeName}}
{{::travel.warehouseOutName}}
@@ -34,14 +42,27 @@
{{::travel.shipped | date:'dd/MM/yyyy'}}
-
+
+
+
+
{{::travel.warehouseInName}}
{{::travel.landed | date:'dd/MM/yyyy'}}
-
+
+
+
+
+ {{::travel.totalEntries}}
-
@@ -78,38 +99,9 @@
fixed-bottom-right>
-
-
-
-
- Filter by selection
-
-
- Exclude selection
-
-
- Remove filter
-
-
- Remove all filters
-
-
- Copy value
-
-
-
\ No newline at end of file
diff --git a/modules/travel/front/index/index.js b/modules/travel/front/index/index.js
index 7701289b78..a570146fe3 100644
--- a/modules/travel/front/index/index.js
+++ b/modules/travel/front/index/index.js
@@ -1,5 +1,6 @@
import ngModule from '../module';
import Section from 'salix/components/section';
+import './style.scss';
export default class Controller extends Section {
preview(travel) {
@@ -30,37 +31,6 @@ export default class Controller extends Section {
if (timeDifference == 0) return 'warning';
if (timeDifference < 0) return 'success';
}
-
- exprBuilder(param, value) {
- switch (param) {
- case 'search':
- return /^\d+$/.test(value)
- ? {'t.id': value}
- : {'t.ref': {like: `%${value}%`}};
- case 'ref':
- return {'t.ref': {like: `%${value}%`}};
- case 'shipped':
- return {'t.shipped': {between: this.dateRange(value)}};
- case 'landed':
- return {'t.landed': {between: this.dateRange(value)}};
- case 'id':
- case 'agencyModeFk':
- case 'warehouseOutFk':
- case 'warehouseInFk':
- case 'totalEntries':
- param = `t.${param}`;
- return {[param]: value};
- }
- }
-
- dateRange(value) {
- const minHour = new Date(value);
- minHour.setHours(0, 0, 0, 0);
- const maxHour = new Date(value);
- maxHour.setHours(23, 59, 59, 59);
-
- return [minHour, maxHour];
- }
}
ngModule.vnComponent('vnTravelIndex', {
diff --git a/modules/travel/front/index/style.scss b/modules/travel/front/index/style.scss
new file mode 100644
index 0000000000..ca1cf538be
--- /dev/null
+++ b/modules/travel/front/index/style.scss
@@ -0,0 +1,11 @@
+@import "variables";
+
+vn-travel-index {
+ vn-icon {
+ color: $color-font-secondary
+ }
+
+ vn-icon.active {
+ color: $color-success
+ }
+}
diff --git a/modules/travel/front/locale/es.yml b/modules/travel/front/locale/es.yml
index 7231d37cda..043702b99c 100644
--- a/modules/travel/front/locale/es.yml
+++ b/modules/travel/front/locale/es.yml
@@ -1,7 +1,7 @@
#Ordenar alfabeticamente
Reference: Referencia
-Warehouse Out: Almacén salida
-Warehouse In: Almacén llegada
+Warehouse Out: Alm salida
+Warehouse In: Alm llegada
Shipped from: Salida desde
Shipped to: Salida hasta
Landed from: Llegada desde
@@ -10,12 +10,12 @@ Shipped: F. salida
Landed: F. llegada
Delivered: Enviado
Received: Recibido
-Travel id: Id envío
-Search travels by id: Buscar envíos por identificador
+Travel id: Id
+Search travels by id: Buscar envíos por identificador o referencia
New travel: Nuevo envío
travel: envío
# Sections
Travels: Envíos
Log: Historial
-Thermographs: Termógrafos
\ No newline at end of file
+Thermographs: Termógrafos
diff --git a/modules/travel/front/main/index.html b/modules/travel/front/main/index.html
index feb1e8b017..131d9409e2 100644
--- a/modules/travel/front/main/index.html
+++ b/modules/travel/front/main/index.html
@@ -1,20 +1,6 @@
-
-
-
-
-
\ No newline at end of file
+
diff --git a/modules/travel/front/main/index.js b/modules/travel/front/main/index.js
index fbaf78c164..6a153f21a4 100644
--- a/modules/travel/front/main/index.js
+++ b/modules/travel/front/main/index.js
@@ -4,28 +4,6 @@ import ModuleMain from 'salix/components/module-main';
export default class Travel extends ModuleMain {
constructor() {
super();
-
- this.filterParams = {
- scopeDays: 1
- };
- }
-
- fetchParams($params) {
- if (!Object.entries($params).length)
- $params.scopeDays = 1;
-
- if (typeof $params.scopeDays === 'number') {
- const shippedFrom = Date.vnNew();
- shippedFrom.setHours(0, 0, 0, 0);
-
- const shippedTo = new Date(shippedFrom.getTime());
- shippedTo.setDate(shippedTo.getDate() + $params.scopeDays);
- shippedTo.setHours(23, 59, 59, 999);
-
- Object.assign($params, {shippedFrom, shippedTo});
- }
-
- return $params;
}
}
diff --git a/modules/travel/front/main/index.spec.js b/modules/travel/front/main/index.spec.js
deleted file mode 100644
index bf5a27b410..0000000000
--- a/modules/travel/front/main/index.spec.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import './index.js';
-
-describe('Travel Component vnTravel', () => {
- let controller;
-
- beforeEach(ngModule('travel'));
-
- beforeEach(inject($componentController => {
- let $element = angular.element(``);
- controller = $componentController('vnTravel', {$element});
- }));
-
- describe('fetchParams()', () => {
- it('should return a range of dates with passed scope days', () => {
- let params = controller.fetchParams({
- scopeDays: 2
- });
- const shippedFrom = Date.vnNew();
- shippedFrom.setHours(0, 0, 0, 0);
- const shippedTo = new Date(shippedFrom.getTime());
- shippedTo.setDate(shippedTo.getDate() + params.scopeDays);
- shippedTo.setHours(23, 59, 59, 999);
-
- const expectedParams = {
- shippedFrom,
- scopeDays: params.scopeDays,
- shippedTo
- };
-
- 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);
- });
- });
-});
diff --git a/modules/travel/front/search-panel/index.html b/modules/travel/front/search-panel/index.html
index 2e9c796c32..dd8d98af1b 100644
--- a/modules/travel/front/search-panel/index.html
+++ b/modules/travel/front/search-panel/index.html
@@ -1,109 +1,146 @@
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Id/{{$ctrl.$t('Reference')}}: {{$ctrl.filter.search}}
+
+
+ {{$ctrl.$t('Agency')}}: {{agency.selection.name}}
+
+
+ {{$ctrl.$t('Warehouse Out')}}: {{warehouseOut.selection.name}}
+
+
+ {{$ctrl.$t('Warehouse In')}}: {{warehouseIn.selection.name}}
+
+
+ {{$ctrl.$t('Days onward')}}: {{$ctrl.filter.scopeDays}}
+
+
+ {{$ctrl.$t('Landed from')}}: {{$ctrl.filter.landedFrom | date:'dd/MM/yyyy'}}
+
+
+ {{$ctrl.$t('Landed to')}}: {{$ctrl.filter.landedTo | date:'dd/MM/yyyy'}}
+
+
+ {{$ctrl.$t('Continent Out')}}: {{continent.selection.name}}
+
+
+ {{$ctrl.$t('Total entries')}}: {{$ctrl.filter.totalEntries}}
+
+
+
diff --git a/modules/travel/front/search-panel/index.js b/modules/travel/front/search-panel/index.js
index 877d4f9d3e..9cf417da10 100644
--- a/modules/travel/front/search-panel/index.js
+++ b/modules/travel/front/search-panel/index.js
@@ -1,43 +1,69 @@
import ngModule from '../module';
import SearchPanel from 'core/components/searchbar/search-panel';
+import './style.scss';
class Controller extends SearchPanel {
constructor($, $element) {
super($, $element);
- this.filter = this.$.filter;
+ this.initFilter();
+ this.fetchData();
}
- get shippedFrom() {
- return this._shippedFrom;
+ $onChanges() {
+ if (this.model)
+ this.applyFilters();
}
- set shippedFrom(value) {
- this._shippedFrom = value;
- this.filter.scopeDays = null;
+ fetchData() {
+ this.$http.get('AgencyModes').then(res => {
+ this.agencyModes = res.data;
+ });
+ this.$http.get('Warehouses').then(res => {
+ this.warehouses = res.data;
+ });
+ this.$http.get('Continents').then(res => {
+ this.continents = res.data;
+ });
}
- get shippedTo() {
- return this._shippedTo;
+ initFilter() {
+ this.filter = {};
+ if (this.$params.q) {
+ this.filter = JSON.parse(this.$params.q);
+ this.search = this.filter.search;
+ this.totalEntries = this.filter.totalEntries;
+ }
+ if (!this.filter.scopeDays) this.filter.scopeDays = 7;
}
- set shippedTo(value) {
- this._shippedTo = value;
- this.filter.scopeDays = null;
+ applyFilters(param) {
+ this.model.applyFilter({}, this.filter)
+ .then(() => {
+ if (param && this.model._orgData.length === 1)
+ this.$state.go('travel.card.summary', {id: this.model._orgData[0].id});
+ else
+ this.$state.go(this.$state.current.name, {q: JSON.stringify(this.filter)}, {location: 'replace'});
+ });
}
- get scopeDays() {
- return this._scopeDays;
+ removeParamFilter(param) {
+ if (this[param]) delete this[param];
+ delete this.filter[param];
+ this.applyFilters();
}
- set scopeDays(value) {
- this._scopeDays = value;
-
- this.filter.shippedFrom = null;
- this.filter.shippedTo = null;
+ onKeyPress($event, param) {
+ if ($event.key === 'Enter') {
+ this.filter[param] = this[param];
+ this.applyFilters(param === 'search');
+ }
}
}
ngModule.vnComponent('vnTravelSearchPanel', {
template: require('./index.html'),
- controller: Controller
+ controller: Controller,
+ bindings: {
+ model: '<'
+ }
});
diff --git a/modules/travel/front/search-panel/index.spec.js b/modules/travel/front/search-panel/index.spec.js
index 884f4fb179..488143e80c 100644
--- a/modules/travel/front/search-panel/index.spec.js
+++ b/modules/travel/front/search-panel/index.spec.js
@@ -8,41 +8,31 @@ describe('Travel Component vnTravelSearchPanel', () => {
beforeEach(inject($componentController => {
controller = $componentController('vnTravelSearchPanel', {$element: null});
controller.$t = () => {};
- controller.filter = {};
}));
- describe('shippedFrom() setter', () => {
- it('should clear the scope days when setting the from property', () => {
- controller.filter.scopeDays = 1;
+ describe('applyFilters()', () => {
+ it('should apply filters', async() => {
+ controller.filter = {foo: 'bar'};
+ controller.model = {
+ applyFilter: jest.fn().mockResolvedValue(),
+ _orgData: [{id: 1}]
+ };
+ controller.$state = {
+ current: {
+ name: 'foo'
+ },
+ go: jest.fn()
+ };
- controller.shippedFrom = Date.vnNew();
+ await controller.applyFilters(true);
- expect(controller.filter.scopeDays).toBeNull();
- expect(controller.shippedFrom).toBeDefined();
- });
- });
+ expect(controller.model.applyFilter).toHaveBeenCalledWith({}, controller.filter);
+ expect(controller.$state.go).toHaveBeenCalledWith('travel.card.summary', {id: 1});
- describe('shippedTo() setter', () => {
- it('should clear the scope days when setting the to property', () => {
- controller.filter.scopeDays = 1;
+ await controller.applyFilters(false);
- controller.shippedTo = Date.vnNew();
-
- expect(controller.filter.scopeDays).toBeNull();
- expect(controller.shippedTo).toBeDefined();
- });
- });
-
- describe('scopeDays() setter', () => {
- it('should clear the date range when setting the scopeDays property', () => {
- controller.filter.shippedFrom = Date.vnNew();
- controller.filter.shippedTo = Date.vnNew();
-
- controller.scopeDays = 1;
-
- expect(controller.filter.shippedFrom).toBeNull();
- expect(controller.filter.shippedTo).toBeNull();
- expect(controller.scopeDays).toBeDefined();
+ expect(controller.$state.go).toHaveBeenCalledWith(controller.$state.current.name,
+ {q: JSON.stringify(controller.filter)}, {location: 'replace'});
});
});
});
diff --git a/modules/travel/front/search-panel/style.scss b/modules/travel/front/search-panel/style.scss
new file mode 100644
index 0000000000..94fe7b2395
--- /dev/null
+++ b/modules/travel/front/search-panel/style.scss
@@ -0,0 +1,37 @@
+@import "variables";
+
+vn-travel-search-panel vn-side-menu {
+ .menu {
+ min-width: $right-menu-width;
+ }
+ & > div {
+ .input {
+ padding-left: $spacing-md;
+ padding-right: $spacing-md;
+ border-color: $color-spacer;
+ border-bottom: $border-thin;
+ }
+ .horizontal {
+ padding-left: $spacing-md;
+ padding-right: $spacing-md;
+ grid-auto-flow: column;
+ grid-column-gap: $spacing-sm;
+ align-items: center;
+ }
+ .chips {
+ display: flex;
+ flex-wrap: wrap;
+ padding: $spacing-md;
+ overflow: hidden;
+ max-width: 100%;
+ border-color: $color-spacer;
+ }
+
+ .or {
+ align-self: center;
+ font-weight: bold;
+ font-size: 26px;
+ color: $color-font-secondary;
+ }
+ }
+}
diff --git a/modules/travel/front/summary/locale/es.yml b/modules/travel/front/summary/locale/es.yml
index aa002fad05..aa6adc9381 100644
--- a/modules/travel/front/summary/locale/es.yml
+++ b/modules/travel/front/summary/locale/es.yml
@@ -1,9 +1,9 @@
Reference: Referencia
-Warehouse In: Almacén entrada
-Warehouse Out: Almacén salida
+Warehouse In: Alm. entrada
+Warehouse Out: Alm. salida
Shipped: F. envío
Landed: F. entrega
-Total entries: Entradas totales
+Total entries: Ent. totales
Delivered: Enviada
Received: Recibida
Agency: Agencia
diff --git a/modules/wagon/back/methods/wagonType/createWagonType.js b/modules/wagon/back/methods/wagonType/createWagonType.js
new file mode 100644
index 0000000000..fed915b28e
--- /dev/null
+++ b/modules/wagon/back/methods/wagonType/createWagonType.js
@@ -0,0 +1,57 @@
+module.exports = Self => {
+ Self.remoteMethodCtx('createWagonType', {
+ description: 'Creates a new wagon type',
+ accessType: 'WRITE',
+ accepts: [
+ {
+ arg: 'name',
+ type: 'String',
+ required: true
+ },
+ {
+ arg: 'divisible',
+ type: 'boolean',
+ required: true
+ }, {
+ arg: 'trays',
+ type: 'any',
+ required: true
+ }
+ ],
+ http: {
+ path: `/createWagonType`,
+ verb: 'PATCH'
+ }
+ });
+
+ Self.createWagonType = async(ctx, options) => {
+ const args = ctx.args;
+ const models = Self.app.models;
+ const myOptions = {};
+ let tx;
+
+ if (typeof options == 'object')
+ Object.assign(myOptions, options);
+
+ if (!myOptions.transaction) {
+ tx = await Self.beginTransaction({});
+ myOptions.transaction = tx;
+ }
+
+ try {
+ const newWagonType = await models.WagonType.create({name: args.name, divisible: args.divisible}, myOptions);
+ args.trays.forEach(async tray => {
+ await models.WagonTypeTray.create({
+ typeFk: newWagonType.id,
+ height: tray.position,
+ colorFk: tray.color.id
+ }, myOptions);
+ });
+
+ if (tx) await tx.commit();
+ } catch (e) {
+ if (tx) await tx.rollback();
+ throw e;
+ }
+ };
+};
diff --git a/modules/wagon/back/methods/wagonType/deleteWagonType.js b/modules/wagon/back/methods/wagonType/deleteWagonType.js
new file mode 100644
index 0000000000..46b65e32f8
--- /dev/null
+++ b/modules/wagon/back/methods/wagonType/deleteWagonType.js
@@ -0,0 +1,43 @@
+module.exports = Self => {
+ Self.remoteMethodCtx('deleteWagonType', {
+ description: 'Deletes a wagon type',
+ accessType: 'WRITE',
+ accepts: [
+ {
+ arg: 'id',
+ type: 'Number',
+ required: true
+ }
+ ],
+ http: {
+ path: `/deleteWagonType`,
+ verb: 'DELETE'
+ }
+ });
+
+ Self.deleteWagonType = async(ctx, options) => {
+ const args = ctx.args;
+ const models = Self.app.models;
+ const myOptions = {};
+ let tx;
+
+ if (typeof options == 'object')
+ Object.assign(myOptions, options);
+
+ if (!myOptions.transaction) {
+ tx = await Self.beginTransaction({});
+ myOptions.transaction = tx;
+ }
+
+ try {
+ await models.Wagon.destroyAll({typeFk: args.id}, myOptions);
+ await models.WagonTypeTray.destroyAll({typeFk: args.id}, myOptions);
+ await models.WagonType.destroyAll({id: args.id}, myOptions);
+
+ if (tx) await tx.commit();
+ } catch (e) {
+ if (tx) await tx.rollback();
+ throw e;
+ }
+ };
+};
diff --git a/modules/wagon/back/methods/wagonType/editWagonType.js b/modules/wagon/back/methods/wagonType/editWagonType.js
new file mode 100644
index 0000000000..bd5ad1f168
--- /dev/null
+++ b/modules/wagon/back/methods/wagonType/editWagonType.js
@@ -0,0 +1,64 @@
+module.exports = Self => {
+ Self.remoteMethodCtx('editWagonType', {
+ description: 'Edits a new wagon type',
+ accessType: 'WRITE',
+ accepts: [
+ {
+ arg: 'id',
+ type: 'String',
+ required: true
+ },
+ {
+ arg: 'name',
+ type: 'String',
+ required: true
+ },
+ {
+ arg: 'divisible',
+ type: 'boolean',
+ required: true
+ }, {
+ arg: 'trays',
+ type: 'any',
+ required: true
+ }
+ ],
+ http: {
+ path: `/editWagonType`,
+ verb: 'PATCH'
+ }
+ });
+
+ Self.editWagonType = async(ctx, options) => {
+ const args = ctx.args;
+ const models = Self.app.models;
+ const myOptions = {};
+ let tx;
+
+ if (typeof options == 'object')
+ Object.assign(myOptions, options);
+
+ if (!myOptions.transaction) {
+ tx = await Self.beginTransaction({});
+ myOptions.transaction = tx;
+ }
+
+ try {
+ const wagonType = await models.WagonType.findById(args.id, null, myOptions);
+ wagonType.updateAttributes({name: args.name, divisible: args.divisible}, myOptions);
+ models.WagonTypeTray.destroyAll({typeFk: args.id}, myOptions);
+ args.trays.forEach(async tray => {
+ await models.WagonTypeTray.create({
+ typeFk: args.id,
+ height: tray.position,
+ colorFk: tray.color.id
+ }, myOptions);
+ });
+
+ if (tx) await tx.commit();
+ } catch (e) {
+ if (tx) await tx.rollback();
+ throw e;
+ }
+ };
+};
diff --git a/modules/wagon/back/methods/wagonType/specs/crudWagonType.spec.js b/modules/wagon/back/methods/wagonType/specs/crudWagonType.spec.js
new file mode 100644
index 0000000000..92ac61060a
--- /dev/null
+++ b/modules/wagon/back/methods/wagonType/specs/crudWagonType.spec.js
@@ -0,0 +1,63 @@
+const models = require('vn-loopback/server/server').models;
+
+describe('WagonType crudWagonType()', () => {
+ const ctx = {
+ args: {
+ name: 'Mock wagon type',
+ divisible: true,
+ trays: [{position: 0, color: {id: 1}},
+ {position: 50, color: {id: 2}},
+ {position: 100, color: {id: 3}}]
+ }
+ };
+
+ it(`should create, edit and delete a new wagon type and its trays`, async() => {
+ const tx = await models.WagonType.beginTransaction({});
+
+ try {
+ const options = {transaction: tx};
+
+ // create
+ await models.WagonType.createWagonType(ctx, options);
+
+ const newWagonType = await models.WagonType.findOne({where: {name: ctx.args.name}}, options);
+ const newWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options);
+
+ expect(newWagonType).not.toEqual(null);
+ expect(newWagonType.name).toEqual(ctx.args.name);
+ expect(newWagonType.divisible).toEqual(ctx.args.divisible);
+ expect(newWagonTrays.length).toEqual(ctx.args.trays.length);
+
+ ctx.args = {
+ id: newWagonType.id,
+ name: 'Edited wagon type',
+ divisible: false,
+ trays: [{position: 0, color: {id: 1}}]
+ };
+
+ // edit
+ await models.WagonType.editWagonType(ctx, options);
+
+ const editedWagonType = await models.WagonType.findById(newWagonType.id, null, options);
+ const editedWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options);
+
+ expect(editedWagonType.name).toEqual(ctx.args.name);
+ expect(editedWagonType.divisible).toEqual(ctx.args.divisible);
+ expect(editedWagonTrays.length).toEqual(ctx.args.trays.length);
+
+ // delete
+ await models.WagonType.deleteWagonType(ctx, options);
+
+ const deletedWagonType = await models.WagonType.findById(newWagonType.id, null, options);
+ const deletedWagonTrays = await models.WagonTypeTray.find({where: {typeFk: newWagonType.id}}, options);
+
+ expect(deletedWagonType).toEqual(null);
+ expect(deletedWagonTrays).toEqual([]);
+
+ await tx.rollback();
+ } catch (e) {
+ await tx.rollback();
+ throw e;
+ }
+ });
+});
diff --git a/modules/wagon/back/model-config.json b/modules/wagon/back/model-config.json
new file mode 100644
index 0000000000..279d55e5c1
--- /dev/null
+++ b/modules/wagon/back/model-config.json
@@ -0,0 +1,23 @@
+{
+ "Wagon": {
+ "dataSource": "vn"
+ },
+ "WagonType": {
+ "dataSource": "vn"
+ },
+ "WagonTypeColor": {
+ "dataSource": "vn"
+ },
+ "WagonTypeTray": {
+ "dataSource": "vn"
+ },
+ "WagonConfig": {
+ "dataSource": "vn"
+ },
+ "CollectionWagon": {
+ "dataSource": "vn"
+ },
+ "CollectionWagonTicket": {
+ "dataSource": "vn"
+ }
+}
diff --git a/modules/wagon/back/models/collection-wagon-ticket.json b/modules/wagon/back/models/collection-wagon-ticket.json
new file mode 100644
index 0000000000..04527205cc
--- /dev/null
+++ b/modules/wagon/back/models/collection-wagon-ticket.json
@@ -0,0 +1,43 @@
+{
+ "name": "CollectionWagonTicket",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "collectionWagonTicket"
+ }
+ },
+ "properties": {
+ "ticketFk": {
+ "id": true,
+ "type": "number"
+ },
+ "wagonFk": {
+ "type": "number",
+ "required": true
+ },
+ "trayFk": {
+ "type": "number",
+ "required": true
+ },
+ "side": {
+ "type": "string"
+ }
+ },
+ "relations": {
+ "ticket": {
+ "type": "belongsTo",
+ "model": "Ticket",
+ "foreignKey": "ticketFk"
+ },
+ "wagon": {
+ "type": "belongsTo",
+ "model": "Wagon",
+ "foreignKey": "wagonFk"
+ },
+ "tray": {
+ "type": "belongsTo",
+ "model": "WagonTypeTray",
+ "foreignKey": "trayFk"
+ }
+ }
+}
diff --git a/modules/wagon/back/models/collection-wagon.json b/modules/wagon/back/models/collection-wagon.json
new file mode 100644
index 0000000000..f3f237428d
--- /dev/null
+++ b/modules/wagon/back/models/collection-wagon.json
@@ -0,0 +1,34 @@
+{
+ "name": "CollectionWagon",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "collectionWagon"
+ }
+ },
+ "properties": {
+ "collectionFk": {
+ "id": true,
+ "type": "number"
+ },
+ "wagonFk": {
+ "type": "number",
+ "required": true
+ },
+ "position": {
+ "type": "number"
+ }
+ },
+ "relations": {
+ "collection": {
+ "type": "belongsTo",
+ "model": "Collection",
+ "foreignKey": "collectionFk"
+ },
+ "wagon": {
+ "type": "belongsTo",
+ "model": "Wagon",
+ "foreignKey": "wagonFk"
+ }
+ }
+}
diff --git a/modules/wagon/back/models/wagon-config.json b/modules/wagon/back/models/wagon-config.json
new file mode 100644
index 0000000000..3d96e28645
--- /dev/null
+++ b/modules/wagon/back/models/wagon-config.json
@@ -0,0 +1,30 @@
+{
+ "name": "WagonConfig",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "wagonConfig"
+ }
+ },
+ "properties": {
+ "id": {
+ "id": true,
+ "type": "number"
+ },
+ "width": {
+ "type": "number"
+ },
+ "height": {
+ "type": "string"
+ },
+ "maxWagonHeight": {
+ "type": "number"
+ },
+ "minHeightBetweenTrays": {
+ "type": "number"
+ },
+ "maxTrays": {
+ "type": "number"
+ }
+ }
+}
diff --git a/modules/wagon/back/models/wagon-type-color.json b/modules/wagon/back/models/wagon-type-color.json
new file mode 100644
index 0000000000..573fd60f52
--- /dev/null
+++ b/modules/wagon/back/models/wagon-type-color.json
@@ -0,0 +1,21 @@
+{
+ "name": "WagonTypeColor",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "wagonTypeColor"
+ }
+ },
+ "properties": {
+ "id": {
+ "id": true,
+ "type": "number"
+ },
+ "name": {
+ "type": "string"
+ },
+ "rgb": {
+ "type": "string"
+ }
+ }
+}
diff --git a/modules/wagon/back/models/wagon-type-tray.json b/modules/wagon/back/models/wagon-type-tray.json
new file mode 100644
index 0000000000..b61510bcf6
--- /dev/null
+++ b/modules/wagon/back/models/wagon-type-tray.json
@@ -0,0 +1,36 @@
+{
+ "name": "WagonTypeTray",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "wagonTypeTray"
+ }
+ },
+ "properties": {
+ "id": {
+ "id": true,
+ "type": "number"
+ },
+ "typeFk": {
+ "type": "number"
+ },
+ "height": {
+ "type": "number"
+ },
+ "colorFk": {
+ "type": "number"
+ }
+ },
+ "relations": {
+ "type": {
+ "type": "belongsTo",
+ "model": "WagonType",
+ "foreignKey": "typeFk"
+ },
+ "color": {
+ "type": "belongsTo",
+ "model": "WagonTypeColor",
+ "foreignKey": "colorFk"
+ }
+ }
+}
diff --git a/modules/wagon/back/models/wagon-type.js b/modules/wagon/back/models/wagon-type.js
new file mode 100644
index 0000000000..bebf7a9d9b
--- /dev/null
+++ b/modules/wagon/back/models/wagon-type.js
@@ -0,0 +1,5 @@
+module.exports = Self => {
+ require('../methods/wagonType/createWagonType')(Self);
+ require('../methods/wagonType/editWagonType')(Self);
+ require('../methods/wagonType/deleteWagonType')(Self);
+};
diff --git a/modules/wagon/back/models/wagon-type.json b/modules/wagon/back/models/wagon-type.json
new file mode 100644
index 0000000000..f57bf957d7
--- /dev/null
+++ b/modules/wagon/back/models/wagon-type.json
@@ -0,0 +1,21 @@
+{
+ "name": "WagonType",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "wagonType"
+ }
+ },
+ "properties": {
+ "id": {
+ "id": true,
+ "type": "number"
+ },
+ "name": {
+ "type": "string"
+ },
+ "divisible": {
+ "type": "boolean"
+ }
+ }
+}
diff --git a/modules/wagon/back/models/wagon.json b/modules/wagon/back/models/wagon.json
new file mode 100644
index 0000000000..61ee61e61b
--- /dev/null
+++ b/modules/wagon/back/models/wagon.json
@@ -0,0 +1,34 @@
+{
+ "name": "Wagon",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "wagon"
+ }
+ },
+ "properties": {
+ "id": {
+ "id": true,
+ "type": "number"
+ },
+ "label": {
+ "type": "number"
+ },
+ "volume": {
+ "type": "number"
+ },
+ "plate": {
+ "type": "string"
+ },
+ "typeFk": {
+ "type": "number"
+ }
+ },
+ "relations": {
+ "type": {
+ "type": "belongsTo",
+ "model": "WagonType",
+ "foreignKey": "typeFk"
+ }
+ }
+}
diff --git a/package.json b/package.json
index 3d0fc4aedf..8fa1776460 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "salix-back",
- "version": "23.12.01",
+ "version": "23.14.01",
"author": "Verdnatura Levante SL",
"description": "Salix backend",
"license": "GPL-3.0",