diff --git a/modules/route/back/methods/trunk/clone.js b/modules/route/back/methods/trunk/clone.js
new file mode 100644
index 0000000000..06d7aed938
--- /dev/null
+++ b/modules/route/back/methods/trunk/clone.js
@@ -0,0 +1,65 @@
+module.exports = Self => {
+ Self.remoteMethod('clone', {
+ description: 'Clones the selected routes',
+ accessType: 'WRITE',
+ accepts: [
+ {
+ arg: 'ids',
+ type: ['number'],
+ required: true,
+ description: 'The routes ids to clone'
+ },
+ {
+ arg: 'ETD',
+ type: 'date',
+ required: true,
+ description: 'The estimated time of departure for all roadmaps'
+ }
+ ],
+ returns: {
+ type: ['Object'],
+ root: true
+ },
+ http: {
+ path: `/clone`,
+ verb: 'POST'
+ }
+ });
+
+ Self.clone = async(ids, ETD) => {
+ const tx = await Self.beginTransaction({});
+ try {
+ const models = Self.app.models;
+ const options = {transaction: tx};
+ const originalRoadmaps = await models.Roadmap.find({
+ where: {id: {inq: ids}},
+ fields: [
+ 'tractorPlate',
+ 'trailerPlate',
+ 'phone',
+ 'supplierFk',
+ 'etd',
+ 'observations',
+ 'userFk',
+ 'price']
+ }, options);
+
+ if (ids.length != originalRoadmaps.length)
+ throw new Error(`The amount of roadmaps found don't match`);
+
+ const roadmaps = originalRoadmaps.map(roadmap => {
+ roadmap.etd = ETD;
+ return roadmap;
+ });
+
+ const clones = await models.Roadmap.create(roadmaps, options);
+
+ await tx.commit();
+
+ return clones;
+ } catch (e) {
+ await tx.rollback();
+ throw e;
+ }
+ };
+};
diff --git a/modules/route/back/methods/trunk/specs/clone.spec.js b/modules/route/back/methods/trunk/specs/clone.spec.js
new file mode 100644
index 0000000000..496ae1c89a
--- /dev/null
+++ b/modules/route/back/methods/trunk/specs/clone.spec.js
@@ -0,0 +1,47 @@
+const app = require('vn-loopback/server/server');
+const LoopBackContext = require('loopback-context');
+
+describe('route clone()', () => {
+ beforeAll(async() => {
+ const activeCtx = {
+ accessToken: {userId: 9},
+ http: {
+ req: {
+ headers: {origin: 'http://localhost'}
+ }
+ }
+ };
+
+ spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
+ active: activeCtx
+ });
+ });
+
+ const createdDate = Date.vnNew();
+ it('should throw an error if the amount of ids pased to the clone function do no match the database', async() => {
+ const ids = [996, 997, 998, 999];
+
+ let error;
+
+ try {
+ await app.models.Route.clone(ids, createdDate);
+ } catch (e) {
+ error = e;
+ }
+
+ expect(error).toBeDefined();
+ expect(error.message).toEqual(`The amount of routes found don't match`);
+ });
+
+ it('should clone two routes', async() => {
+ const ids = [1, 2];
+
+ const clones = await app.models.Route.clone(ids, createdDate);
+
+ expect(clones.length).toEqual(2);
+
+ // restores
+ for (const clone of clones)
+ await app.models.Route.destroyById(clone.id);
+ });
+});
diff --git a/modules/route/back/models/roadmap.js b/modules/route/back/models/roadmap.js
new file mode 100644
index 0000000000..949700d4f7
--- /dev/null
+++ b/modules/route/back/models/roadmap.js
@@ -0,0 +1,3 @@
+module.exports = Self => {
+ require('../methods/trunk/clone')(Self);
+};
diff --git a/modules/route/back/models/roadmap.json b/modules/route/back/models/roadmap.json
index 5afddad41b..ba3ad75cb1 100644
--- a/modules/route/back/models/roadmap.json
+++ b/modules/route/back/models/roadmap.json
@@ -32,6 +32,9 @@
},
"userFk": {
"type": "number"
+ },
+ "price": {
+ "type": "number"
}
}
}
diff --git a/modules/route/front/trunk/create/index.html b/modules/route/front/trunk/create/index.html
index 0d4d87cdd0..df1ac45cdf 100644
--- a/modules/route/front/trunk/create/index.html
+++ b/modules/route/front/trunk/create/index.html
@@ -1,108 +1,78 @@
-
+ url="Roadmaps"
+ data="$ctrl.roadmap"
+ insert-mode="true"
+ form="form">
-
-
-
-
-
-
-
diff --git a/modules/route/front/trunk/create/index.js b/modules/route/front/trunk/create/index.js
index b2d634866a..4315a84199 100644
--- a/modules/route/front/trunk/create/index.js
+++ b/modules/route/front/trunk/create/index.js
@@ -1,111 +1,14 @@
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!'));
- });
+ this.$.watcher.submit().then(
+ res => {
+ this.$state.go('trunk.card.summary', {id: res.data.id});
}
- });
- }
-
- onFileChange(files) {
- let hasFileAttached = false;
-
- if (files.length > 0)
- hasFileAttached = true;
-
- this.$.$applyAsync(() => {
- this.dms.hasFileAttached = hasFileAttached;
- });
+ );
}
}
@@ -113,8 +16,5 @@ Controller.$inject = ['$element', '$scope'];
ngModule.vnComponent('vnTrunkCreate', {
template: require('./index.html'),
- controller: Controller,
- bindings: {
- route: '<'
- }
+ controller: Controller
});
diff --git a/modules/route/front/trunk/index/index.html b/modules/route/front/trunk/index/index.html
index ed36608524..36a8a5d3c6 100644
--- a/modules/route/front/trunk/index/index.html
+++ b/modules/route/front/trunk/index/index.html
@@ -20,10 +20,9 @@
+ ng-click="$ctrl.openClonationDialog()"
+ icon="icon-clone"
+ vn-tooltip="Clone selected trunks">
@@ -79,15 +78,13 @@
-
-
-
-
+
+
+
@@ -96,3 +93,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/route/front/trunk/index/index.js b/modules/route/front/trunk/index/index.js
index e4300d6719..e56da96c12 100644
--- a/modules/route/front/trunk/index/index.js
+++ b/modules/route/front/trunk/index/index.js
@@ -4,38 +4,6 @@ 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) {
@@ -58,60 +26,46 @@ class Controller extends Section {
}
get checked() {
- const agencyTerms = this.$.model.data || [];
- const checkedAgencyTerms = [];
- for (let agencyTerm of agencyTerms) {
- if (agencyTerm.checked)
- checkedAgencyTerms.push(agencyTerm);
+ const roadmaps = this.$.model.data || [];
+ const checkedRoadmap = [];
+ for (let roadmap of roadmaps) {
+ if (roadmap.checked)
+ checkedRoadmap.push(roadmap);
}
- return checkedAgencyTerms;
+ return checkedRoadmap;
}
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;
+ openClonationDialog() {
+ this.$.clonationDialog.show();
+ this.ETD = Date.vnNew();
+ }
- 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;
- }
+ 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));
}
- const params = JSON.stringify({
- supplierName: this.checked[0].supplierName,
- rows: rowsToCreateInvoiceIn
- });
- this.$state.go('route.agencyTerm.createInvoiceIn', {q: params});
}
}
diff --git a/modules/route/front/trunk/locale/es.yml b/modules/route/front/trunk/locale/es.yml
index 0f6797188b..ad7a6a0cc2 100644
--- a/modules/route/front/trunk/locale/es.yml
+++ b/modules/route/front/trunk/locale/es.yml
@@ -1,5 +1,12 @@
-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
\ No newline at end of file
+Trunks: Troncales
+Trunk: Troncal
+Driver name: Transportista
+Plate: Matrícula
+Price: Precio
+Observations: Observaciones
+Clone selected trunks: Clonar troncales seleccionadas
+Select the estimated time of departure (ETD): Seleccione la hora estimada de salida (ETD)
+Create trunk: Crear troncal
+Tractor plate: Matrícula tractor
+Trailer plate: Matrícula trailer
+