diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index b96b26255..41ed5eb6d 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2564,10 +2564,6 @@ UPDATE `vn`.`route` UPDATE `vn`.`route` SET `invoiceInFk`=2 WHERE `id`=2; -INSERT INTO `bs`.`salesPerson` (`workerFk`, `year`, `month`) - VALUES - (18, YEAR(util.VN_CURDATE()), MONTH(util.VN_CURDATE())), - (19, YEAR(util.VN_CURDATE()), MONTH(util.VN_CURDATE())); INSERT INTO `bs`.`sale` (`saleFk`, `amount`, `dated`, `typeFk`, `clientFk`) VALUES diff --git a/front/salix/components/log/index.js b/front/salix/components/log/index.js index 2796931a0..f30878b9f 100644 --- a/front/salix/components/log/index.js +++ b/front/salix/components/log/index.js @@ -37,7 +37,7 @@ export default class Controller extends Section { const validations = window.validations; value.forEach(log => { - const locale = validations[log.changedModel].locale ? validations[log.changedModel].locale : {}; + const locale = validations[log.changedModel] && validations[log.changedModel].locale ? validations[log.changedModel].locale : {}; log.oldProperties = this.getInstance(log.oldInstance, locale); log.newProperties = this.getInstance(log.newInstance, locale); diff --git a/modules/client/back/methods/client/filter.js b/modules/client/back/methods/client/filter.js index 3e1ea43bb..6a545b594 100644 --- a/modules/client/back/methods/client/filter.js +++ b/modules/client/back/methods/client/filter.js @@ -91,7 +91,10 @@ module.exports = Self => { case 'search': return /^\d+$/.test(value) ? {'c.id': {inq: value}} - : {'c.name': {like: `%${value}%`}}; + : {or: [ + {'c.name': {like: `%${value}%`}}, + {'c.socialName': {like: `%${value}%`}}, + ]}; case 'name': case 'salesPersonFk': case 'fi': diff --git a/modules/route/back/methods/route/getTickets.js b/modules/route/back/methods/route/getTickets.js index 18e5abaf2..708644c1a 100644 --- a/modules/route/back/methods/route/getTickets.js +++ b/modules/route/back/methods/route/getTickets.js @@ -33,36 +33,36 @@ module.exports = Self => { const stmt = new ParameterizedSQL( `SELECT - t.id, - t.packages, - t.warehouseFk, - t.nickname, - t.clientFk, - t.priority, - t.addressFk, - st.code AS ticketStateCode, - st.name AS ticketStateName, - wh.name AS warehouseName, - tob.description AS ticketObservation, - a.street, - a.postalCode, - a.city, - am.name AS agencyModeName, - u.nickname AS userNickname, - vn.ticketTotalVolume(t.id) AS volume, - tob.description - FROM route r - JOIN ticket t ON t.routeFk = r.id - LEFT JOIN ticketState ts ON ts.ticketFk = t.id - LEFT JOIN state st ON st.id = ts.stateFk - LEFT JOIN warehouse wh ON wh.id = t.warehouseFk - LEFT JOIN ticketObservation tob ON tob.ticketFk = t.id - LEFT JOIN observationType ot ON tob.observationTypeFk = ot.id - AND ot.code = 'delivery' - LEFT JOIN address a ON a.id = t.addressFk - LEFT JOIN agencyMode am ON am.id = t.agencyModeFk - LEFT JOIN account.user u ON u.id = r.workerFk - LEFT JOIN vehicle v ON v.id = r.vehicleFk` + t.id, + t.packages, + t.warehouseFk, + t.nickname, + t.clientFk, + t.priority, + t.addressFk, + st.code AS ticketStateCode, + st.name AS ticketStateName, + wh.name AS warehouseName, + tob.description AS ticketObservation, + a.street, + a.postalCode, + a.city, + am.name AS agencyModeName, + u.nickname AS userNickname, + vn.ticketTotalVolume(t.id) AS volume, + tob.description + FROM vn.route r + JOIN ticket t ON t.routeFk = r.id + LEFT JOIN ticketState ts ON ts.ticketFk = t.id + LEFT JOIN state st ON st.id = ts.stateFk + LEFT JOIN warehouse wh ON wh.id = t.warehouseFk + LEFT JOIN observationType ot ON ot.code = 'delivery' + LEFT JOIN ticketObservation tob ON tob.ticketFk = t.id + AND tob.observationTypeFk = ot.id + LEFT JOIN address a ON a.id = t.addressFk + LEFT JOIN agencyMode am ON am.id = t.agencyModeFk + LEFT JOIN account.user u ON u.id = r.workerFk + LEFT JOIN vehicle v ON v.id = r.vehicleFk` ); if (!filter.where) filter.where = {}; diff --git a/modules/worker/back/methods/worker-time-control-mail/checkInbox.js b/modules/worker/back/methods/worker-time-control-mail/checkInbox.js new file mode 100644 index 000000000..7825f38b8 --- /dev/null +++ b/modules/worker/back/methods/worker-time-control-mail/checkInbox.js @@ -0,0 +1,181 @@ +const Imap = require('imap'); +module.exports = Self => { + Self.remoteMethod('checkInbox', { + description: 'Check an email inbox and process it', + accessType: 'READ', + returns: + { + arg: 'body', + type: 'file', + root: true + }, + http: { + path: `/checkInbox`, + verb: 'POST' + } + }); + + Self.checkInbox = async() => { + let imapConfig = await Self.app.models.WorkerTimeControlParams.findOne(); + let imap = new Imap({ + user: imapConfig.mailUser, + password: imapConfig.mailPass, + host: imapConfig.mailHost, + port: 993, + tls: true + }); + let isEmailOk; + let uid; + let emailBody; + + function openInbox(cb) { + imap.openBox('INBOX', true, cb); + } + + imap.once('ready', function() { + openInbox(function(err, box) { + if (err) throw err; + const totalMessages = box.messages.total; + if (totalMessages == 0) + imap.end(); + + let f = imap.seq.fetch('1:*', { + bodies: ['HEADER.FIELDS (FROM SUBJECT)', '1'], + struct: true + }); + f.on('message', function(msg, seqno) { + isEmailOk = false; + msg.on('body', function(stream, info) { + let buffer = ''; + let bufferCopy = ''; + stream.on('data', function(chunk) { + buffer = chunk.toString('utf8'); + if (info.which === '1' && bufferCopy.length == 0) + bufferCopy = buffer.replace(/\s/g, ' '); + }); + stream.on('end', function() { + if (bufferCopy.length > 0) { + emailBody = bufferCopy.toUpperCase().trim(); + + const bodyPositionOK = emailBody.match(/\bOK\b/i); + if (bodyPositionOK != null && (bodyPositionOK.index == 0 || bodyPositionOK.index == 122)) + isEmailOk = true; + else + isEmailOk = false; + } + }); + msg.once('attributes', function(attrs) { + uid = attrs.uid; + }); + msg.once('end', function() { + if (info.which === 'HEADER.FIELDS (FROM SUBJECT)') { + if (isEmailOk) { + imap.move(uid, 'exito', function(err) { + }); + emailConfirm(buffer); + } else { + imap.move(uid, 'error', function(err) { + }); + emailReply(buffer, emailBody); + } + } + }); + }); + }); + f.once('end', function() { + imap.end(); + }); + }); + }); + + imap.connect(); + return 'Leer emails de gestion horaria'; + }; + + async function emailConfirm(buffer) { + const now = new Date(); + const from = JSON.stringify(Imap.parseHeader(buffer).from); + const subject = JSON.stringify(Imap.parseHeader(buffer).subject); + + const timeControlDate = await getEmailDate(subject); + const week = timeControlDate[0]; + const year = timeControlDate[1]; + const user = await getUser(from); + let workerMail; + + if (user.id != null) { + workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ + where: { + week: week, + year: year, + workerFk: user.id + } + }); + } + if (workerMail != null) { + await workerMail.updateAttributes({ + updated: now, + state: 'CONFIRMED' + }); + } + } + + async function emailReply(buffer, emailBody) { + const now = new Date(); + const from = JSON.stringify(Imap.parseHeader(buffer).from); + const subject = JSON.stringify(Imap.parseHeader(buffer).subject); + + const timeControlDate = await getEmailDate(subject); + const week = timeControlDate[0]; + const year = timeControlDate[1]; + const user = await getUser(from); + let workerMail; + + if (user.id != null) { + workerMail = await Self.app.models.WorkerTimeControlMail.findOne({ + where: { + week: week, + year: year, + workerFk: user.id + } + }); + + if (workerMail != null) { + await workerMail.updateAttributes({ + updated: now, + state: 'REVISE', + reason: emailBody + }); + } else + await sendMail(user, subject, emailBody); + } + } + + async function getUser(workerEmail) { + const userEmail = workerEmail.match(/(?<=<)(.*?)(?=>)/); + + let [user] = await Self.rawSql(`SELECT u.id,u.name FROM account.user u + LEFT JOIN account.mailForward m on m.account = u.id + WHERE forwardTo =? OR + CONCAT(u.name,'@verdnatura.es') = ?`, + [userEmail[0], userEmail[0]]); + + return user; + } + + async function getEmailDate(subject) { + const date = subject.match(/\d+/g); + return date; + } + + async function sendMail(user, subject, emailBody) { + const sendTo = 'rrhh@verdnatura.es'; + const emailSubject = subject + ' ' + user.name; + + await Self.app.models.Mail.create({ + receiver: sendTo, + subject: emailSubject, + body: emailBody + }); + } +}; diff --git a/modules/worker/back/methods/worker-time-control/sendMail.js b/modules/worker/back/methods/worker-time-control/sendMail.js index a1d6ea2ac..b38405c1d 100644 --- a/modules/worker/back/methods/worker-time-control/sendMail.js +++ b/modules/worker/back/methods/worker-time-control/sendMail.js @@ -133,7 +133,7 @@ module.exports = Self => { tb.permissionRate, d.isTeleworking FROM tmp.timeBusinessCalculate tb - JOIN user u ON u.id = tb.userFk + JOIN account.user u ON u.id = tb.userFk JOIN department d ON d.id = tb.departmentFk JOIN business b ON b.id = tb.businessFk LEFT JOIN tmp.timeControlCalculate tc ON tc.userFk = tb.userFk AND tc.dated = tb.dated @@ -143,7 +143,7 @@ module.exports = Self => { IF(tc.timeWorkDecimal > 0, FALSE, IF(tb.timeWorkDecimal > 0, TRUE, FALSE)), TRUE))isTeleworkingWeek FROM tmp.timeBusinessCalculate tb - LEFT JOIN tmp.timeControlCalculate tc ON tc.userFk = tb.userFk + LEFT JOIN tmp.timeControlCalculate tc ON tc.userFk = tb.userFk AND tc.dated = tb.dated GROUP BY tb.userFk HAVING isTeleworkingWeek > 0 diff --git a/modules/worker/back/models/worker-time-control-mail.js b/modules/worker/back/models/worker-time-control-mail.js new file mode 100644 index 000000000..36f3851b6 --- /dev/null +++ b/modules/worker/back/models/worker-time-control-mail.js @@ -0,0 +1,3 @@ +module.exports = Self => { + require('../methods/worker-time-control-mail/checkInbox')(Self); +}; diff --git a/print/common/css/misc.css b/print/common/css/misc.css index df8bf571a..ce6c641a0 100644 --- a/print/common/css/misc.css +++ b/print/common/css/misc.css @@ -49,4 +49,10 @@ .page-break-after { page-break-after: always; +} + +.ellipsize { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } \ No newline at end of file diff --git a/print/templates/reports/collection-label/assets/css/style.css b/print/templates/reports/collection-label/assets/css/style.css index fe1975445..597921c92 100644 --- a/print/templates/reports/collection-label/assets/css/style.css +++ b/print/templates/reports/collection-label/assets/css/style.css @@ -1,6 +1,6 @@ html { font-family: "Roboto"; - margin-top: -7px; + margin-top: -6px; } * { box-sizing: border-box; @@ -9,7 +9,7 @@ html { } #vertical { writing-mode: vertical-rl; - height: 226px; + height: 240px; margin-left: -13px; } .outline { @@ -18,6 +18,7 @@ html { } #nickname { font-size: 22px; + max-width: 50px; } #agencyDescripton { font-size: 32px; diff --git a/print/templates/reports/collection-label/collection-label.html b/print/templates/reports/collection-label/collection-label.html index eeb82ac4a..6716d1fe5 100644 --- a/print/templates/reports/collection-label/collection-label.html +++ b/print/templates/reports/collection-label/collection-label.html @@ -1,35 +1,36 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{{labelData.levelV}}{{labelData.ticketFk}} ⬸ {{labelData.clientFk}}{{labelData.shipped}}
{{labelData.workerCode}}
{{labelData.labelCount}}
{{labelData.size}}
{{labelData.agencyDescription}}
{{labelData.lineCount}}
{{labelData.nickName}}{{labelData.agencyHour}}
- -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ {{labelData.collectionFk ? `${labelData.collectionFk} ~ ${labelData.wagon}-${labelData.level}` : '-'.repeat(23)}} + + {{labelData.clientFk ? `${labelData.ticketFk} « ${labelData.clientFk}` : labelData.ticketFk}} + {{labelData.shipped ? labelData.shipped : '---'}}
{{labelData.workerCode ? labelData.workerCode : '---'}}
{{labelData.labelCount ? labelData.labelCount : 0}}
{{labelData.code == 'plant' ? labelData.size + 'cm' : labelData.volume + 'm³'}}
{{labelData.agencyDescription}}
{{labelData.lineCount ? labelData.lineCount : 0}}
{{labelData.nickName ? labelData.nickName : '---'}}{{labelData.shipped ? labelData.shippedHour : labelData.zoneHour}}
+ + \ No newline at end of file diff --git a/print/templates/reports/collection-label/collection-label.js b/print/templates/reports/collection-label/collection-label.js index 7bc25ad79..d2d5f6417 100644 --- a/print/templates/reports/collection-label/collection-label.js +++ b/print/templates/reports/collection-label/collection-label.js @@ -40,7 +40,7 @@ module.exports = { format: 'code128', displayValue: false, width: 3.8, - height: 110, + height: 115, }); return xmlSerializer.serializeToString(svgNode); }, diff --git a/print/templates/reports/collection-label/options.json b/print/templates/reports/collection-label/options.json index 175b3c1db..ae88e6c0c 100644 --- a/print/templates/reports/collection-label/options.json +++ b/print/templates/reports/collection-label/options.json @@ -2,8 +2,8 @@ "width": "10.4cm", "height": "4.8cm", "margin": { - "top": "0cm", - "right": "0.5cm", + "top": "0.3cm", + "right": "0.6cm", "bottom": "0cm", "left": "0cm" }, diff --git a/print/templates/reports/collection-label/sql/labelsData.sql b/print/templates/reports/collection-label/sql/labelsData.sql index 6f5b47a54..b799b289b 100644 --- a/print/templates/reports/collection-label/sql/labelsData.sql +++ b/print/templates/reports/collection-label/sql/labelsData.sql @@ -1,21 +1,23 @@ -SELECT c.itemPackingTypeFk, - CONCAT(tc.collectionFk, ' ', LEFT(cc.code, 4)) color, - CONCAT(tc.collectionFk, ' ', SUBSTRING('ABCDEFGH',tc.wagon, 1), '-', tc.`level`) levelV, - tc.ticketFk, - LEFT(COALESCE(et.description, zo.name, am.name),12) agencyDescription, +SELECT tc.collectionFk, + SUBSTRING('ABCDEFGH', tc.wagon, 1) wagon, + tc.`level`, + t.id ticketFk, + COALESCE(et.description, zo.name, am.name) agencyDescription, am.name, t.clientFk, - CONCAT(CAST(SUM(sv.volume) AS DECIMAL(5, 2)), 'm³') m3 , - CAST(IF(ic.code = 'plant', CONCAT(MAX(i.`size`),' cm'), COUNT(*)) AS CHAR) size, + CAST(SUM(sv.volume) AS DECIMAL(5, 2)) volume, + MAX(i.`size`) `size`, + ic.code, w.code workerCode, - tt.labelCount, - IF(HOUR(t.shipped), TIME_FORMAT(t.shipped, '%H:%i'), TIME_FORMAT(zo.`hour`, '%H:%i')) agencyHour, + TIME_FORMAT(t.shipped, '%H:%i') shippedHour, + TIME_FORMAT(zo.`hour`, '%H:%i') zoneHour, DATE_FORMAT(t.shipped, '%d/%m/%y') shipped, - COUNT(*) lineCount, - t.nickName + t.nickName, + tt.labelCount, + COUNT(*) lineCount FROM vn.ticket t - JOIN vn.ticketCollection tc ON tc.ticketFk = t.id - JOIN vn.collection c ON c.id = tc.collectionFk + LEFT JOIN vn.ticketCollection tc ON tc.ticketFk = t.id + LEFT JOIN vn.collection c ON c.id = tc.collectionFk LEFT JOIN vn.collectionColors cc ON cc.shelve = tc.`level` AND cc.wagon = tc.wagon AND cc.trainFk = c.trainFk @@ -24,12 +26,12 @@ SELECT c.itemPackingTypeFk, JOIN vn.item i ON i.id = s.itemFk JOIN vn.itemType it ON it.id = i.typeFk JOIN vn.itemCategory ic ON ic.id = it.categoryFk - JOIN vn.worker w ON w.id = c.workerFk + LEFT JOIN vn.worker w ON w.id = c.workerFk JOIN vn.agencyMode am ON am.id = t.agencyModeFk LEFT JOIN vn.ticketTrolley tt ON tt.ticket = t.id LEFT JOIN vn.`zone` zo ON t.zoneFk = zo.id LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk LEFT JOIN vn.expeditionTruck et ON et.id = rm.expeditionTruckFk - WHERE tc.ticketFk IN (?) + WHERE t.id IN (?) GROUP BY t.id ORDER BY cc.`code`; \ No newline at end of file