@@ -27,7 +27,7 @@
{{::clientSms.sms.destination}}
- {{::clientSms.sms.message}}
+ {{::clientSms.sms.message}}
{{::clientSms.sms.status}}
{{::clientSms.sms.created | date:'dd/MM/yyyy HH:mm'}}
diff --git a/modules/item/front/fetched-tags/index.html b/modules/item/front/fetched-tags/index.html
index 472fa676b7..df5936871c 100644
--- a/modules/item/front/fetched-tags/index.html
+++ b/modules/item/front/fetched-tags/index.html
@@ -1,40 +1,40 @@
-
-
-
\ No newline at end of file
+
diff --git a/modules/item/front/fetched-tags/style.scss b/modules/item/front/fetched-tags/style.scss
index 2cd7afbb21..250ca07abf 100644
--- a/modules/item/front/fetched-tags/style.scss
+++ b/modules/item/front/fetched-tags/style.scss
@@ -28,7 +28,7 @@
vn-fetched-tags {
& > vn-horizontal {
align-items: center;
-
+ max-width: 210px;
& > vn-auto {
flex-wrap: wrap;
@@ -43,19 +43,19 @@ vn-fetched-tags {
& > .inline-tag {
color: $color-font-secondary;
text-align: center;
- font-size: .75rem;
- height: 12px;
+ font-size: .8rem;
+ height: 13px;
padding: 1px;
width: 64px;
min-width: 64px;
max-width: 64px;
flex: 1;
- border: 1px solid $color-spacer;
-
+ border: 1px solid $color-font-secondary;
+
&.empty {
- border: 1px solid $color-spacer-light;
+ border: 1px solid darken($color-font-secondary, 30%);
}
}
}
}
-}
\ No newline at end of file
+}
diff --git a/modules/route/back/methods/route/cmr.js b/modules/route/back/methods/route/cmr.js
new file mode 100644
index 0000000000..cd7ef57cee
--- /dev/null
+++ b/modules/route/back/methods/route/cmr.js
@@ -0,0 +1,36 @@
+module.exports = Self => {
+ Self.remoteMethodCtx('cmr', {
+ description: 'Returns the cmr',
+ accessType: 'READ',
+ accepts: [
+ {
+ arg: 'id',
+ type: 'number',
+ required: true,
+ description: 'The cmr id',
+ http: {source: 'path'}
+ }
+ ],
+ returns: [
+ {
+ arg: 'body',
+ type: 'file',
+ root: true
+ }, {
+ arg: 'Content-Type',
+ type: 'String',
+ http: {target: 'header'}
+ }, {
+ arg: 'Content-Disposition',
+ type: 'String',
+ http: {target: 'header'}
+ }
+ ],
+ http: {
+ path: '/:id/cmr',
+ verb: 'GET'
+ }
+ });
+
+ Self.cmr = (ctx, id) => Self.printReport(ctx, id, 'cmr');
+};
diff --git a/modules/route/back/methods/route/getExternalCmrs.js b/modules/route/back/methods/route/getExternalCmrs.js
new file mode 100644
index 0000000000..5b08cf34ae
--- /dev/null
+++ b/modules/route/back/methods/route/getExternalCmrs.js
@@ -0,0 +1,133 @@
+const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
+const buildFilter = require('vn-loopback/util/filter').buildFilter;
+const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
+
+module.exports = Self => {
+ Self.remoteMethod('getExternalCmrs', {
+ description: 'Returns an array of external cmrs',
+ accessType: 'READ',
+ accepts: [
+ {
+ arg: 'filter',
+ type: 'object',
+ description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
+ },
+ {
+ arg: 'cmrFk',
+ type: 'integer',
+ description: 'Searchs the route by id',
+ },
+ {
+ arg: 'ticketFk',
+ type: 'integer',
+ description: 'The worker id',
+ },
+ {
+ arg: 'country',
+ type: 'string',
+ description: 'The agencyMode id',
+ },
+ {
+ arg: 'clientFk',
+ type: 'integer',
+ description: 'The vehicle id',
+ },
+ {
+ arg: 'hasCmrDms',
+ type: 'boolean',
+ description: 'The vehicle id',
+ },
+ {
+ arg: 'shipped',
+ type: 'date',
+ description: 'The to date filter',
+ },
+ ],
+ returns: {
+ type: ['object'],
+ root: true
+ },
+ http: {
+ path: `/getExternalCmrs`,
+ verb: 'GET'
+ }
+ });
+
+ Self.getExternalCmrs = async(
+ filter,
+ cmrFk,
+ ticketFk,
+ country,
+ clientFk,
+ hasCmrDms,
+ shipped,
+ options
+ ) => {
+ const params = {
+ cmrFk,
+ ticketFk,
+ country,
+ clientFk,
+ hasCmrDms,
+ shipped,
+ };
+ const conn = Self.dataSource.connector;
+
+ let where = buildFilter(params, (param, value) => {return {[param]: value}});
+ filter = mergeFilters(filter, {where});
+
+ if (!filter.where) {
+ const yesterday = new Date();
+ yesterday.setDate(yesterday.getDate() - 1);
+ filter.where = {'shipped': yesterday.toISOString().split('T')[0]}
+ }
+
+ const myOptions = {};
+
+ if (typeof options == 'object')
+ Object.assign(myOptions, options);
+
+ let stmts = [];
+ const stmt = new ParameterizedSQL(`
+ SELECT *
+ FROM (
+ SELECT t.cmrFk,
+ t.id ticketFk,
+ co.country,
+ t.clientFk,
+ sub.id hasCmrDms,
+ DATE(t.shipped) shipped
+ FROM ticket t
+ JOIN ticketState ts ON ts.ticketFk = t.id
+ JOIN state s ON s.id = ts.stateFk
+ JOIN alertLevel al ON al.id = s.alertLevel
+ JOIN client c ON c.id = t.clientFk
+ JOIN address a ON a.id = t.addressFk
+ JOIN province p ON p.id = a.provinceFk
+ JOIN country co ON co.id = p.countryFk
+ JOIN agencyMode am ON am.id = t.agencyModeFk
+ JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk
+ JOIN warehouse w ON w.id = t.warehouseFk
+ LEFT JOIN (
+ SELECT td.ticketFk, d.id
+ FROM ticketDms td
+ JOIN dms d ON d.id = td.dmsFk
+ JOIN dmsType dt ON dt.id = d.dmsTypeFk
+ WHERE dt.name = 'cmr'
+ ) sub ON sub.ticketFk = t.id
+ WHERE co.code <> 'ES'
+ AND am.name <> 'ABONO'
+ AND w.code = 'ALG'
+ AND dm.code = 'DELIVERY'
+ AND t.cmrFk
+ ) sub
+ `);
+
+ stmt.merge(conn.makeSuffix(filter));
+ const itemsIndex = stmts.push(stmt) - 1;
+
+ const sql = ParameterizedSQL.join(stmts, ';');
+ const result = await conn.executeStmt(sql);
+ return itemsIndex === 0 ? result : result[itemsIndex];
+ };
+};
diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js
index 883f4597e4..7e61acf25f 100644
--- a/modules/route/back/models/route.js
+++ b/modules/route/back/models/route.js
@@ -14,6 +14,8 @@ module.exports = Self => {
require('../methods/route/driverRouteEmail')(Self);
require('../methods/route/sendSms')(Self);
require('../methods/route/downloadZip')(Self);
+ require('../methods/route/cmr')(Self);
+ require('../methods/route/getExternalCmrs')(Self);
Self.validate('kmStart', validateDistance, {
message: 'Distance must be lesser than 1000'
@@ -28,5 +30,5 @@ module.exports = Self => {
const routeMaxKm = 1000;
if (routeTotalKm > routeMaxKm || this.kmStart > this.kmEnd)
err();
- }
+ };
};
diff --git a/modules/route/front/roadmap/index/index.js b/modules/route/front/roadmap/index/index.js
index 3ffc5b4b1b..c5f5ef9d1c 100644
--- a/modules/route/front/roadmap/index/index.js
+++ b/modules/route/front/roadmap/index/index.js
@@ -46,8 +46,6 @@ class Controller extends Section {
}
deleteRoadmaps() {
- console.log(this.checked);
-
for (const roadmap of this.checked) {
this.$http.delete(`Roadmaps/${roadmap.id}`)
.then(() => this.$.model.refresh())
diff --git a/modules/ticket/back/methods/ticket/closure.js b/modules/ticket/back/methods/ticket/closure.js
index eee5e28e26..9f9aec9bd1 100644
--- a/modules/ticket/back/methods/ticket/closure.js
+++ b/modules/ticket/back/methods/ticket/closure.js
@@ -5,177 +5,177 @@ const config = require('vn-print/core/config');
const storage = require('vn-print/core/storage');
module.exports = async function(ctx, Self, tickets, reqArgs = {}) {
- const userId = ctx.req.accessToken.userId;
- if (tickets.length == 0) return;
+ const userId = ctx.req.accessToken.userId;
+ if (tickets.length == 0) return;
- const failedtickets = [];
- for (const ticket of tickets) {
- try {
- await Self.rawSql(`CALL vn.ticket_closeByTicket(?)`, [ticket.id], {userId});
+ const failedtickets = [];
+ for (const ticket of tickets) {
+ try {
+ await Self.rawSql(`CALL vn.ticket_closeByTicket(?)`, [ticket.id], {userId});
- const [invoiceOut] = await Self.rawSql(`
- SELECT io.id, io.ref, io.serial, cny.code companyCode, io.issued
- FROM ticket t
- JOIN invoiceOut io ON io.ref = t.refFk
- JOIN company cny ON cny.id = io.companyFk
- WHERE t.id = ?
- `, [ticket.id]);
+ const [invoiceOut] = await Self.rawSql(`
+ SELECT io.id, io.ref, io.serial, cny.code companyCode, io.issued
+ FROM ticket t
+ JOIN invoiceOut io ON io.ref = t.refFk
+ JOIN company cny ON cny.id = io.companyFk
+ WHERE t.id = ?
+ `, [ticket.id]);
- const mailOptions = {
- overrideAttachments: true,
- attachments: []
- };
+ const mailOptions = {
+ overrideAttachments: true,
+ attachments: []
+ };
- const isToBeMailed = ticket.recipient && ticket.salesPersonFk && ticket.isToBeMailed;
+ const isToBeMailed = ticket.recipient && ticket.salesPersonFk && ticket.isToBeMailed;
- if (invoiceOut) {
- const args = {
- reference: invoiceOut.ref,
- recipientId: ticket.clientFk,
- recipient: ticket.recipient,
- replyTo: ticket.salesPersonEmail
- };
+ if (invoiceOut) {
+ const args = {
+ reference: invoiceOut.ref,
+ recipientId: ticket.clientFk,
+ recipient: ticket.recipient,
+ replyTo: ticket.salesPersonEmail
+ };
- const invoiceReport = new Report('invoice', args);
- const stream = await invoiceReport.toPdfStream();
+ const invoiceReport = new Report('invoice', args);
+ const stream = await invoiceReport.toPdfStream();
- const issued = invoiceOut.issued;
- const year = issued.getFullYear().toString();
- const month = (issued.getMonth() + 1).toString();
- const day = issued.getDate().toString();
+ const issued = invoiceOut.issued;
+ const year = issued.getFullYear().toString();
+ const month = (issued.getMonth() + 1).toString();
+ const day = issued.getDate().toString();
- const fileName = `${year}${invoiceOut.ref}.pdf`;
+ const fileName = `${year}${invoiceOut.ref}.pdf`;
- // Store invoice
- await storage.write(stream, {
- type: 'invoice',
- path: `${year}/${month}/${day}`,
- fileName: fileName
- });
+ // Store invoice
+ await storage.write(stream, {
+ type: 'invoice',
+ path: `${year}/${month}/${day}`,
+ fileName: fileName
+ });
- await Self.rawSql('UPDATE invoiceOut SET hasPdf = true WHERE id = ?', [invoiceOut.id], {userId});
+ await Self.rawSql('UPDATE invoiceOut SET hasPdf = true WHERE id = ?', [invoiceOut.id], {userId});
- if (isToBeMailed) {
- const invoiceAttachment = {
- filename: fileName,
- content: stream
- };
+ if (isToBeMailed) {
+ const invoiceAttachment = {
+ filename: fileName,
+ content: stream
+ };
- if (invoiceOut.serial == 'E' && invoiceOut.companyCode == 'VNL') {
- const exportation = new Report('exportation', args);
- const stream = await exportation.toPdfStream();
- const fileName = `CITES-${invoiceOut.ref}.pdf`;
+ if (invoiceOut.serial == 'E' && invoiceOut.companyCode == 'VNL') {
+ const exportation = new Report('exportation', args);
+ const stream = await exportation.toPdfStream();
+ const fileName = `CITES-${invoiceOut.ref}.pdf`;
- mailOptions.attachments.push({
- filename: fileName,
- content: stream
- });
- }
+ mailOptions.attachments.push({
+ filename: fileName,
+ content: stream
+ });
+ }
- mailOptions.attachments.push(invoiceAttachment);
+ mailOptions.attachments.push(invoiceAttachment);
- const email = new Email('invoice', args);
- await email.send(mailOptions);
- }
- } else if (isToBeMailed) {
- const args = {
- id: ticket.id,
- recipientId: ticket.clientFk,
- recipient: ticket.recipient,
- replyTo: ticket.salesPersonEmail
- };
+ const email = new Email('invoice', args);
+ await email.send(mailOptions);
+ }
+ } else if (isToBeMailed) {
+ const args = {
+ id: ticket.id,
+ recipientId: ticket.clientFk,
+ recipient: ticket.recipient,
+ replyTo: ticket.salesPersonEmail
+ };
- const email = new Email('delivery-note-link', args);
- await email.send();
- }
+ const email = new Email('delivery-note-link', args);
+ await email.send();
+ }
- // Incoterms authorization
- const [{firstOrder}] = await Self.rawSql(`
- SELECT COUNT(*) as firstOrder
- FROM ticket t
- JOIN client c ON c.id = t.clientFk
- WHERE t.clientFk = ?
- AND NOT t.isDeleted
- AND c.isVies
- `, [ticket.clientFk]);
+ // Incoterms authorization
+ const [{firstOrder}] = await Self.rawSql(`
+ SELECT COUNT(*) as firstOrder
+ FROM ticket t
+ JOIN client c ON c.id = t.clientFk
+ WHERE t.clientFk = ?
+ AND NOT t.isDeleted
+ AND c.isVies
+ `, [ticket.clientFk]);
- if (firstOrder == 1) {
- const args = {
- id: ticket.clientFk,
- companyId: ticket.companyFk,
- recipientId: ticket.clientFk,
- recipient: ticket.recipient,
- replyTo: ticket.salesPersonEmail
- };
+ if (firstOrder == 1) {
+ const args = {
+ id: ticket.clientFk,
+ companyId: ticket.companyFk,
+ recipientId: ticket.clientFk,
+ recipient: ticket.recipient,
+ replyTo: ticket.salesPersonEmail
+ };
- const email = new Email('incoterms-authorization', args);
- await email.send();
+ const email = new Email('incoterms-authorization', args);
+ await email.send();
- const [sample] = await Self.rawSql(
- `SELECT id
- FROM sample
- WHERE code = 'incoterms-authorization'
- `);
+ const [sample] = await Self.rawSql(
+ `SELECT id
+ FROM sample
+ WHERE code = 'incoterms-authorization'
+ `);
- await Self.rawSql(`
- INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?)
- `, [ticket.clientFk, sample.id, ticket.companyFk], {userId});
- }
- } catch (error) {
- // Domain not found
- if (error.responseCode == 450)
- return invalidEmail(ticket);
+ await Self.rawSql(`
+ INSERT INTO clientSample (clientFk, typeFk, companyFk) VALUES(?, ?, ?)
+ `, [ticket.clientFk, sample.id, ticket.companyFk], {userId});
+ };
+ } catch (error) {
+ // Domain not found
+ if (error.responseCode == 450)
+ return invalidEmail(ticket);
- // Save tickets on a list of failed ids
- failedtickets.push({
- id: ticket.id,
- stacktrace: error
- });
- }
- }
+ // Save tickets on a list of failed ids
+ failedtickets.push({
+ id: ticket.id,
+ stacktrace: error
+ });
+ }
+ }
- // Send email with failed tickets
- if (failedtickets.length > 0) {
- let body = 'This following tickets have failed:
';
+ // Send email with failed tickets
+ if (failedtickets.length > 0) {
+ let body = 'This following tickets have failed:
';
- for (const ticket of failedtickets) {
- body += `Ticket: ${ticket.id}
-
${ticket.stacktrace}
`;
- }
+ for (const ticket of failedtickets) {
+ body += `Ticket: ${ticket.id}
+
${ticket.stacktrace}
`;
+ }
- smtp.send({
- to: config.app.reportEmail,
- subject: '[API] Nightly ticket closure report',
- html: body
- });
- }
+ smtp.send({
+ to: config.app.reportEmail,
+ subject: '[API] Nightly ticket closure report',
+ html: body
+ });
+ }
- async function invalidEmail(ticket) {
- await Self.rawSql(`UPDATE client SET email = NULL WHERE id = ?`, [
- ticket.clientFk
- ], {userId});
+ async function invalidEmail(ticket) {
+ await Self.rawSql(`UPDATE client SET email = NULL WHERE id = ?`, [
+ ticket.clientFk
+ ], {userId});
- const oldInstance = `{"email": "${ticket.recipient}"}`;
- const newInstance = `{"email": ""}`;
- await Self.rawSql(`
- INSERT INTO clientLog (originFk, userFk, action, changedModel, oldInstance, newInstance)
- VALUES (?, NULL, 'UPDATE', 'Client', ?, ?)`, [
- ticket.clientFk,
- oldInstance,
- newInstance
- ], {userId});
+ const oldInstance = `{"email": "${ticket.recipient}"}`;
+ const newInstance = `{"email": ""}`;
+ await Self.rawSql(`
+ INSERT INTO clientLog (originFk, userFk, action, changedModel, oldInstance, newInstance)
+ VALUES (?, NULL, 'UPDATE', 'Client', ?, ?)`, [
+ ticket.clientFk,
+ oldInstance,
+ newInstance
+ ], {userId});
- const body = `No se ha podido enviar el albarán ${ticket.id}
- al cliente ${ticket.clientFk} - ${ticket.clientName}
- porque la dirección de email "${ticket.recipient}" no es correcta
- o no está disponible.
- Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente.
- Actualiza la dirección de email con una correcta.`;
+ const body = `No se ha podido enviar el albarán ${ticket.id}
+ al cliente ${ticket.clientFk} - ${ticket.clientName}
+ porque la dirección de email "${ticket.recipient}" no es correcta
+ o no está disponible.
+ Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente.
+ Actualiza la dirección de email con una correcta.`;
- smtp.send({
- to: ticket.salesPersonEmail,
- subject: 'No se ha podido enviar el albarán',
- html: body
- });
- }
+ smtp.send({
+ to: ticket.salesPersonEmail,
+ subject: 'No se ha podido enviar el albarán',
+ html: body
+ });
+ }
};
diff --git a/modules/ticket/back/methods/ticket/componentUpdate.js b/modules/ticket/back/methods/ticket/componentUpdate.js
index b5ff50d59f..8aad8959bb 100644
--- a/modules/ticket/back/methods/ticket/componentUpdate.js
+++ b/modules/ticket/back/methods/ticket/componentUpdate.js
@@ -1,4 +1,5 @@
const loggable = require('vn-loopback/util/log');
+const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('componentUpdate', {
@@ -112,7 +113,6 @@ module.exports = Self => {
}
try {
- const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const $t = ctx.req.__; // $translate
await models.Ticket.isEditableOrThrow(ctx, args.id, myOptions);
@@ -127,11 +127,8 @@ module.exports = Self => {
args.warehouseFk,
myOptions);
- if (!zoneShipped || zoneShipped.zoneFk != args.zoneFk) {
- const error = `You don't have privileges to change the zone`;
-
- throw new UserError(error);
- }
+ if (!zoneShipped || zoneShipped.zoneFk != args.zoneFk)
+ throw new UserError(`You don't have privileges to change the zone`);
}
if (args.isWithoutNegatives) {
diff --git a/modules/ticket/back/methods/ticket/filter.js b/modules/ticket/back/methods/ticket/filter.js
index 262b3fd743..eb3da39aff 100644
--- a/modules/ticket/back/methods/ticket/filter.js
+++ b/modules/ticket/back/methods/ticket/filter.js
@@ -248,6 +248,7 @@ module.exports = Self => {
am.name AS agencyMode,
am.id AS agencyModeFk,
st.name AS state,
+ st.classColor,
wk.lastName AS salesPerson,
ts.stateFk AS stateFk,
ts.alertLevel AS alertLevel,
@@ -339,7 +340,8 @@ module.exports = Self => {
{'tp.isFreezed': hasProblem},
{'tp.risk': hasProblem},
{'tp.hasTicketRequest': hasProblem},
- {'tp.itemShortage': range}
+ {'tp.itemShortage': range},
+ {'tp.hasRounding': hasProblem}
]};
if (hasWhere)
diff --git a/modules/ticket/back/methods/ticket/getTicketsFuture.js b/modules/ticket/back/methods/ticket/getTicketsFuture.js
index 901e546f75..fa24cc379d 100644
--- a/modules/ticket/back/methods/ticket/getTicketsFuture.js
+++ b/modules/ticket/back/methods/ticket/getTicketsFuture.js
@@ -194,7 +194,8 @@ module.exports = Self => {
{'tp.hasTicketRequest': hasProblem},
{'tp.itemShortage': range},
{'tp.hasComponentLack': hasProblem},
- {'tp.isTooLittle': hasProblem}
+ {'tp.isTooLittle': hasProblem},
+ {'tp.hasRounding': hasProblem}
]
};
diff --git a/modules/ticket/back/methods/ticket/specs/transferSales.spec.js b/modules/ticket/back/methods/ticket/specs/transferSales.spec.js
index ef92e88c0f..69829fe668 100644
--- a/modules/ticket/back/methods/ticket/specs/transferSales.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/transferSales.spec.js
@@ -5,6 +5,8 @@ describe('sale transferSales()', () => {
const userId = 1101;
const activeCtx = {
accessToken: {userId: userId},
+ headers: {origin: ''},
+ __: value => value
};
const ctx = {req: activeCtx};
diff --git a/modules/ticket/back/methods/ticket/transferSales.js b/modules/ticket/back/methods/ticket/transferSales.js
index a48c5683ca..1124f7ec70 100644
--- a/modules/ticket/back/methods/ticket/transferSales.js
+++ b/modules/ticket/back/methods/ticket/transferSales.js
@@ -37,6 +37,7 @@ module.exports = Self => {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const myOptions = {userId};
+ const $t = ctx.req.__; // $translate
let tx;
if (typeof options == 'object')
@@ -95,9 +96,18 @@ module.exports = Self => {
const isTicketEmpty = await models.Ticket.isEmpty(id, myOptions);
if (isTicketEmpty) {
- await originalTicket.updateAttributes({
- isDeleted: true
- }, myOptions);
+ try {
+ await models.Ticket.setDeleted(ctx, id, myOptions);
+ } catch (e) {
+ if (e.statusCode === 400) {
+ throw new UserError(
+ `This ticket cannot be left empty.`,
+ 'TRANSFER_SET_DELETED',
+ $t(e.message, ...e.translateArgs)
+ );
+ }
+ throw e;
+ }
}
if (tx) await tx.commit();
diff --git a/modules/ticket/back/models/state.json b/modules/ticket/back/models/state.json
index 9d4dd4f5d6..8b7eb69c69 100644
--- a/modules/ticket/back/models/state.json
+++ b/modules/ticket/back/models/state.json
@@ -27,6 +27,9 @@
"code": {
"type": "string",
"required": false
+ },
+ "classColor": {
+ "type": "string"
}
}
}
diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html
index 78b0f98645..5119d103b5 100644
--- a/modules/ticket/front/future/index.html
+++ b/modules/ticket/front/future/index.html
@@ -123,6 +123,12 @@
class="bright"
icon="icon-components">
+
+
+
+
{{::ticket.id}}
diff --git a/modules/ticket/front/routes.json b/modules/ticket/front/routes.json
index c86b3a1efc..e403ab02dc 100644
--- a/modules/ticket/front/routes.json
+++ b/modules/ticket/front/routes.json
@@ -26,7 +26,8 @@
{"state": "ticket.card.components", "icon": "icon-components"},
{"state": "ticket.card.saleTracking", "icon": "assignment"},
{"state": "ticket.card.dms.index", "icon": "cloud_download"},
- {"state": "ticket.card.boxing", "icon": "science"}
+ {"state": "ticket.card.boxing", "icon": "science"},
+ {"state": "ticket.card.sms", "icon": "sms"}
]
},
"keybindings": [
@@ -287,6 +288,15 @@
"state": "ticket.advance",
"component": "vn-ticket-advance",
"description": "Advance tickets"
+ },
+ {
+ "url": "/sms",
+ "state": "ticket.card.sms",
+ "component": "vn-ticket-sms",
+ "description": "Sms",
+ "params": {
+ "ticket": "$ctrl.ticket"
+ }
}
]
}
diff --git a/modules/ticket/front/sms/index.html b/modules/ticket/front/sms/index.html
new file mode 100644
index 0000000000..7fb3b870e0
--- /dev/null
+++ b/modules/ticket/front/sms/index.html
@@ -0,0 +1,2 @@
+
+
diff --git a/modules/ticket/front/sms/index.js b/modules/ticket/front/sms/index.js
new file mode 100644
index 0000000000..69d54aafe8
--- /dev/null
+++ b/modules/ticket/front/sms/index.js
@@ -0,0 +1,21 @@
+import ngModule from '../module';
+import Section from 'salix/components/section';
+
+class Controller extends Section {
+ constructor($element, $) {
+ super($element, $);
+ }
+
+ async $onInit() {
+ this.$state.go('ticket.card.summary', {id: this.$params.id});
+ window.location.href = await this.vnApp.getUrl(`ticket/${this.$params.id}/sms`);
+ }
+}
+
+ngModule.vnComponent('vnTicketSms', {
+ template: require('./index.html'),
+ controller: Controller,
+ bindings: {
+ ticket: '<'
+ }
+});
diff --git a/modules/worker/back/methods/worker-dms/filter.js b/modules/worker/back/methods/worker-dms/filter.js
index 5f55f1bd71..9d85544848 100644
--- a/modules/worker/back/methods/worker-dms/filter.js
+++ b/modules/worker/back/methods/worker-dms/filter.js
@@ -71,8 +71,9 @@ module.exports = Self => {
'Stored on': 'created',
'Document ID': 'id'
};
+
workerDocuware =
- await models.Docuware.getById('hr', worker.lastName + worker.firstName, docuwareParse) ?? [];
+ await models.Docuware.getById('hr', worker.lastName + ' ' + worker.firstName, docuwareParse) ?? [];
for (document of workerDocuware) {
const defaultData = {
file: 'dw' + document.id + '.png',
diff --git a/modules/worker/back/methods/worker/specs/new.spec.js b/modules/worker/back/methods/worker/specs/new.spec.js
index b2804c2031..d0830b00f6 100644
--- a/modules/worker/back/methods/worker/specs/new.spec.js
+++ b/modules/worker/back/methods/worker/specs/new.spec.js
@@ -20,11 +20,11 @@ describe('Worker new', () => {
const employeeId = 1;
const defaultWorker = {
fi: '78457139E',
- name: 'defaultWorker',
- firstName: 'default',
- lastNames: 'worker',
+ name: 'DEFAULTERWORKER',
+ firstName: 'DEFAULT',
+ lastNames: 'WORKER',
email: 'defaultWorker@mydomain.com',
- street: 'S/ defaultWorkerStreet',
+ street: 'S/ DEFAULTWORKERSTREET',
city: 'defaultWorkerCity',
provinceFk: 1,
companyFk: 442,
diff --git a/package-lock.json b/package-lock.json
index f87e3f64b8..10b5e6b022 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "salix-back",
- "version": "23.34.01",
+ "version": "23.32.02",
"lockfileVersion": 2,
"requires": true,
"packages": {
diff --git a/print/templates/reports/cmr/assets/css/import.js b/print/templates/reports/cmr/assets/css/import.js
new file mode 100644
index 0000000000..37a98dfddb
--- /dev/null
+++ b/print/templates/reports/cmr/assets/css/import.js
@@ -0,0 +1,12 @@
+const Stylesheet = require(`vn-print/core/stylesheet`);
+
+const path = require('path');
+const vnPrintPath = path.resolve('print');
+
+module.exports = new Stylesheet([
+ `${vnPrintPath}/common/css/spacing.css`,
+ `${vnPrintPath}/common/css/misc.css`,
+ `${vnPrintPath}/common/css/layout.css`,
+ `${vnPrintPath}/common/css/report.css`,
+ `${__dirname}/style.css`])
+ .mergeStyles();
diff --git a/print/templates/reports/cmr/assets/css/style.css b/print/templates/reports/cmr/assets/css/style.css
new file mode 100644
index 0000000000..201afc3b60
--- /dev/null
+++ b/print/templates/reports/cmr/assets/css/style.css
@@ -0,0 +1,101 @@
+html {
+ font-family: "Roboto", "Helvetica", "Arial", sans-serif;
+ margin: 10px;
+ font-size: 22px;
+}
+.mainTable, .specialTable, .categoryTable {
+ width: 100%;
+ border-collapse: collapse;
+ font-size: inherit;
+}
+.mainTable td {
+ width: 50%;
+ border: 1px solid black;
+ vertical-align: top;
+ padding: 15px;
+ font-size: inherit;
+}
+.signTable {
+ height: 12%;
+}
+.signTable td {
+ width: calc(100% / 3);
+ border: 1px solid black;
+ vertical-align: top;
+ font-size: inherit;
+ padding: 15px;
+ border-top: none;
+}
+#title {
+ font-weight: bold;
+ font-size: 85px;
+}
+hr {
+ border: 1px solid #cccccc;
+ height: 0px;
+ border-radius: 25px;
+}
+#cellHeader {
+ border: 0px;
+ text-align: center;
+ vertical-align: middle;
+}
+#label, #merchandiseLabels {
+ font-size: 13px;
+}
+#merchandiseLabels {
+ border: none;
+}
+.imgSection {
+ text-align: center;
+ height: 200px;
+ overflow: hidden;
+}
+img {
+ object-fit: contain;
+ width: 100%;
+ height: 100%;
+}
+#lineBreak {
+ white-space: pre-line;
+}
+.specialTable td {
+ border: 1px solid black;
+ vertical-align: top;
+ padding: 15px;
+ font-size: inherit;
+ border-top: none;
+ border-bottom: none;
+}
+.specialTable #itemCategoryList {
+ width: 70%;
+ padding-top: 10px;
+}
+.categoryTable {
+ padding-bottom: none;
+}
+.categoryTable td {
+ vertical-align: top;
+ font-size: inherit;
+ border: none;
+ padding: 5px;
+ overflow: hidden;
+}
+.categoryTable #merchandiseLabels {
+ border-bottom: 4px solid #cccccc;
+ padding: none;
+}
+#merchandiseDetail {
+ font-weight: bold;
+ padding-top: 10px;
+}
+#merchandiseData {
+ font-weight: bold;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+#merchandiseLabels td {
+ padding-bottom: 11px;
+ max-width: 300px;
+}
\ No newline at end of file
diff --git a/print/templates/reports/cmr/cmr.html b/print/templates/reports/cmr/cmr.html
new file mode 100644
index 0000000000..c6a9e79d6e
--- /dev/null
+++ b/print/templates/reports/cmr/cmr.html
@@ -0,0 +1,212 @@
+
+
+
+
+
+
+
+ 1. Remitente / Expediteur / Sender
+
+ {{data.senderName}}
+ {{data.senderStreet}}
+ {{data.senderPostCode}} {{data.senderCity}} {{(data.senderCountry) ? `(${data.senderCountry})` : null}}
+ |
+
+
+
+
+ 2. Consignatario / Destinataire / Consignee
+
+ {{data.deliveryAddressFk}}
+ {{data.deliveryName}}
+ {{data.deliveryPhone || data.clientPhone}}
+ {{((data.deliveryPhone || data.clientPhone) && data.deliveryMobile) ? '/' : null}}
+ {{data.deliveryMobile}}
+ |
+
+ 16. Transportista / Transporteur / Carrier
+
+ {{data.carrierName}}
+ {{data.carrierStreet}}
+ {{data.carrierPostalCode}} {{data.carrierCity}} {{(data.carrierCountry) ? `(${data.carrierCountry})` : null}}
+ |
+
+
+
+
+ 3. Lugar y fecha de entrega /
+ Lieu et date de livraison /
+ Place and date of delivery
+
+
+ {{data.deliveryStreet}}
+ {{data.deliveryPostalCode}} {{data.deliveryCity}} {{(data.deliveryCountry) ? `(${data.deliveryCountry})` : null}}
+ {{(data.ead) ? formatDate(data.ead, '%d/%m/%Y') : null}}
+
+ |
+
+ 17. Porteadores sucesivos / Transporteurs succesifs / Succesive Carriers
+
+ |
+
+
+
+
+ 4. Lugar y fecha de carga /
+ Lieu et date del prise en charge de la merchandise /
+ Place and date of taking over the goods
+
+
+ {{data.loadStreet}}
+ {{data.loadPostalCode}} {{data.loadCity}} {{(data.loadCountry) ? `(${data.loadCountry})` : null}}
+ {{formatDate(data.created, '%d/%m/%Y')}}
+ |
+
+
+ 18. Obervaciones del transportista /
+ Reserves et observations du transporteur /
+ Carrier's reservations and observations
+
+
+ {{data.truckPlate}}
+ {{data.observations}}
+ |
+
+
+
+ 5. Documentos anexos / Documents annexes / Documents attached
+
+ |
+
+
+
+
+
+
+ 7 & 8. Número de bultos y clase de embalage /
+ Number of packages and packaging class /
+ Nombre de colis et classe d'emballage
+
+
+
+ {{data.packagesList}}
+
+ |
+
+
+
+ 6. Marcas y números / Brands and numbers / Marques et numéros |
+ 9. Naturaleza de la merc. / Nature of goods / Nature des marchandises |
+ 10. nº Estadístico / Statistical no. / n° statistique |
+ 11. Peso bruto / Gross weight / Poids brut (kg) |
+ 12. Volumen / Volume (m3) |
+
+
+ {{merchandise.ticketFk}} |
+ {{merchandise.name}} |
+ N/A |
+ {{merchandise.weight}} |
+ {{merchandise.volume}} |
+
+
+
+ {{data.merchandiseDetail}}
+
+ |
+
+
+
+
+
+
+ 13. Instrucciones del remitente /
+ Instrunstions de l'expèditeur / Sender
+ instruccions
+
+
+ {{data.senderInstruccions}}
+ |
+
+
+ 19. Estipulaciones particulares /
+ Conventions particulieres /
+ Special agreements
+
+
+ {{data.specialAgreements}}
+ |
+
+
+
+
+ 14. Forma de pago /
+ Prescriptions d'affranchissement /
+ Instruction as to payment for carriage
+
+
+ {{data.paymentInstruccions}}
+ |
+
+ 20. A pagar por / Être payé pour / To be paid by
+
+ |
+
+
+
+ 21. Formalizado en / Etabile a / Estabilshed in
+
+ {{data.loadStreet}}
+ {{data.loadPostalCode}} {{data.loadCity}} {{(data.loadCountry) ? `(${data.loadCountry})` : null}}
+ |
+
+ 15. Reembolso / Remboursement / Cash on delivery
+
+ |
+
+
+
+
+
+
+
+
+
+ 22. Firma y sello del remitente /
+ Signature et timbre de l'expèditeur /
+ Signature and stamp of the sender
+
+
+
+ ![]()
+
+ |
+
+
+ 23. Firma y sello del transportista /
+ Signature et timbre du transporteur /
+ Signature and stamp of the carrier
+
+
+
+ ![]()
+
+ |
+
+
+ 24. Firma y sello del consignatario /
+ Signature et timbre du destinataire /
+ Signature and stamp of the consignee
+
+
+
+ ![]()
+
+ |
+
+
+
+
+
\ No newline at end of file
diff --git a/print/templates/reports/cmr/cmr.js b/print/templates/reports/cmr/cmr.js
new file mode 100644
index 0000000000..c939e51525
--- /dev/null
+++ b/print/templates/reports/cmr/cmr.js
@@ -0,0 +1,45 @@
+const config = require(`vn-print/core/config`);
+const vnReport = require('../../../core/mixins/vn-report.js');
+const md5 = require('md5');
+const fs = require('fs-extra');
+
+const prefixBase64 = 'data:image/png;base64,';
+
+module.exports = {
+ name: 'cmr',
+ mixins: [vnReport],
+ async serverPrefetch() {
+ this.data = await this.findOneFromDef('data', [this.id]);
+ if (this.data.ticketFk) {
+ this.merchandises = await this.rawSqlFromDef('merchandise', [this.data.ticketFk]);
+ this.signature = await this.findOneFromDef('signature', [this.data.ticketFk]);
+ } else
+ this.merchandises = null;
+
+ this.senderStamp = (this.data.senderStamp)
+ ? `${prefixBase64} ${this.data.senderStamp.toString('base64')}`
+ : null;
+ this.deliveryStamp = (this.data.deliveryStamp)
+ ? `${prefixBase64} ${this.data.deliveryStamp.toString('base64')}`
+ : null;
+ },
+ props: {
+ id: {
+ type: Number,
+ required: true,
+ description: 'The cmr id'
+ },
+ },
+ computed: {
+ signPath() {
+ if (!this.signature) return;
+
+ const signatureName = this.signature.signature
+ const hash = md5(signatureName.toString()).substring(0, 3);
+ const file = `${config.storage.root}/${hash}/${signatureName}.png`;
+ if (!fs.existsSync(file)) return null;
+
+ return `${prefixBase64} ${Buffer.from(fs.readFileSync(file), 'utf8').toString('base64')}`;
+ },
+ }
+};
\ No newline at end of file
diff --git a/print/templates/reports/cmr/locale/es.yml b/print/templates/reports/cmr/locale/es.yml
new file mode 100644
index 0000000000..79f481b352
--- /dev/null
+++ b/print/templates/reports/cmr/locale/es.yml
@@ -0,0 +1 @@
+reportName: cmr
\ No newline at end of file
diff --git a/print/templates/reports/cmr/options.json b/print/templates/reports/cmr/options.json
new file mode 100644
index 0000000000..9151ca63b1
--- /dev/null
+++ b/print/templates/reports/cmr/options.json
@@ -0,0 +1,3 @@
+{
+ "format": "A4"
+}
\ No newline at end of file
diff --git a/print/templates/reports/cmr/sql/data.sql b/print/templates/reports/cmr/sql/data.sql
new file mode 100644
index 0000000000..9708c4483c
--- /dev/null
+++ b/print/templates/reports/cmr/sql/data.sql
@@ -0,0 +1,52 @@
+SELECT c.id cmrFk,
+ t.id ticketFk,
+ c.truckPlate,
+ c.observations,
+ c.senderInstruccions,
+ c.paymentInstruccions,
+ c.specialAgreements,
+ c.created,
+ c.packagesList,
+ c.merchandiseDetail,
+ c.ead,
+ s.name carrierName,
+ s.street carrierStreet,
+ s.postCode carrierPostCode,
+ s.city carrierCity,
+ cou.country carrierCountry,
+ s2.name senderName,
+ s2.street senderStreet,
+ s2.postCode senderPostCode,
+ s2.city senderCity,
+ cou2.country senderCountry,
+ a.street deliveryStreet,
+ a.id deliveryAddressFk,
+ a.postalCode deliveryPostalCode,
+ a.city deliveryCity,
+ a.nickname deliveryName,
+ a.phone deliveryPhone,
+ a.mobile deliveryMobile,
+ cou3.country deliveryCountry,
+ cl.phone clientPhone,
+ a2.street loadStreet,
+ a2.postalCode loadPostalCode,
+ a2.city loadCity,
+ cou4.country loadCountry,
+ co.stamp senderStamp,
+ s.stamp deliveryStamp
+ FROM cmr c
+ LEFT JOIN supplier s ON s.id = c.supplierFk
+ LEFT JOIN country cou ON cou.id = s.countryFk
+ LEFT JOIN company co ON co.id = c.companyFk
+ LEFT JOIN supplierAccount sa ON sa.id = co.supplierAccountFk
+ LEFT JOIN supplier s2 ON s2.id = sa.supplierFk
+ LEFT JOIN country cou2 ON cou2.id = s2.countryFk
+ LEFT JOIN `address` a ON a.id = c.addressToFk
+ LEFT JOIN province p ON p.id = a.provinceFk
+ LEFT JOIN country cou3 ON cou3.id = p.countryFk
+ LEFT JOIN client cl ON cl.id = a.clientFk
+ LEFT JOIN `address` a2 ON a2.id = c.addressFromFk
+ LEFT JOIN province p2 ON p2.id = a2.provinceFk
+ LEFT JOIN country cou4 ON cou4.id = p2.countryFk
+ LEFT JOIN ticket t ON t.cmrFk = c.id
+ WHERE c.id = ?
\ No newline at end of file
diff --git a/print/templates/reports/cmr/sql/merchandise.sql b/print/templates/reports/cmr/sql/merchandise.sql
new file mode 100644
index 0000000000..cab597caa2
--- /dev/null
+++ b/print/templates/reports/cmr/sql/merchandise.sql
@@ -0,0 +1,11 @@
+SELECT s.ticketFk,
+ ic.name,
+ CAST(SUM(sv.weight) AS DECIMAL(10,2)) `weight`,
+ CAST(SUM(sv.volume) AS DECIMAL(10,3)) volume
+ FROM sale s
+ JOIN saleVolume sv ON sv.saleFk = s.id
+ JOIN item i ON i.id = s.itemFk
+ JOIN itemType it ON it.id = i.typeFk
+ JOIN itemCategory ic ON ic.id = it.categoryFk
+ WHERE sv.ticketFk = ?
+ GROUP BY ic.id
\ No newline at end of file
diff --git a/print/templates/reports/cmr/sql/signature.sql b/print/templates/reports/cmr/sql/signature.sql
new file mode 100644
index 0000000000..7ec7380a58
--- /dev/null
+++ b/print/templates/reports/cmr/sql/signature.sql
@@ -0,0 +1,5 @@
+SELECT dc.id `signature`
+ FROM ticket t
+ JOIN ticketDms dt ON dt.ticketFk = t.id
+ LEFT JOIN dms dc ON dc.id = dt.dmsFk
+ WHERE t.id = ?
\ No newline at end of file
|