Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 4649-bookEntriesIncorrectly_notification

This commit is contained in:
Vicent Llopis 2022-11-30 08:03:16 +01:00
commit f056c26b0d
13 changed files with 286 additions and 93 deletions

View File

@ -2564,10 +2564,6 @@ UPDATE `vn`.`route`
UPDATE `vn`.`route` UPDATE `vn`.`route`
SET `invoiceInFk`=2 SET `invoiceInFk`=2
WHERE `id`=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`) INSERT INTO `bs`.`sale` (`saleFk`, `amount`, `dated`, `typeFk`, `clientFk`)
VALUES VALUES

View File

@ -37,7 +37,7 @@ export default class Controller extends Section {
const validations = window.validations; const validations = window.validations;
value.forEach(log => { 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.oldProperties = this.getInstance(log.oldInstance, locale);
log.newProperties = this.getInstance(log.newInstance, locale); log.newProperties = this.getInstance(log.newInstance, locale);

View File

@ -91,7 +91,10 @@ module.exports = Self => {
case 'search': case 'search':
return /^\d+$/.test(value) return /^\d+$/.test(value)
? {'c.id': {inq: value}} ? {'c.id': {inq: value}}
: {'c.name': {like: `%${value}%`}}; : {or: [
{'c.name': {like: `%${value}%`}},
{'c.socialName': {like: `%${value}%`}},
]};
case 'name': case 'name':
case 'salesPersonFk': case 'salesPersonFk':
case 'fi': case 'fi':

View File

@ -51,14 +51,14 @@ module.exports = Self => {
u.nickname AS userNickname, u.nickname AS userNickname,
vn.ticketTotalVolume(t.id) AS volume, vn.ticketTotalVolume(t.id) AS volume,
tob.description tob.description
FROM route r FROM vn.route r
JOIN ticket t ON t.routeFk = r.id JOIN ticket t ON t.routeFk = r.id
LEFT JOIN ticketState ts ON ts.ticketFk = t.id LEFT JOIN ticketState ts ON ts.ticketFk = t.id
LEFT JOIN state st ON st.id = ts.stateFk LEFT JOIN state st ON st.id = ts.stateFk
LEFT JOIN warehouse wh ON wh.id = t.warehouseFk 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 LEFT JOIN ticketObservation tob ON tob.ticketFk = t.id
LEFT JOIN observationType ot ON tob.observationTypeFk = ot.id AND tob.observationTypeFk = ot.id
AND ot.code = 'delivery'
LEFT JOIN address a ON a.id = t.addressFk LEFT JOIN address a ON a.id = t.addressFk
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
LEFT JOIN account.user u ON u.id = r.workerFk LEFT JOIN account.user u ON u.id = r.workerFk

View File

@ -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
});
}
};

View File

@ -133,7 +133,7 @@ module.exports = Self => {
tb.permissionRate, tb.permissionRate,
d.isTeleworking d.isTeleworking
FROM tmp.timeBusinessCalculate tb 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 department d ON d.id = tb.departmentFk
JOIN business b ON b.id = tb.businessFk JOIN business b ON b.id = tb.businessFk
LEFT JOIN tmp.timeControlCalculate tc ON tc.userFk = tb.userFk AND tc.dated = tb.dated LEFT JOIN tmp.timeControlCalculate tc ON tc.userFk = tb.userFk AND tc.dated = tb.dated

View File

@ -0,0 +1,3 @@
module.exports = Self => {
require('../methods/worker-time-control-mail/checkInbox')(Self);
};

View File

@ -50,3 +50,9 @@
.page-break-after { .page-break-after {
page-break-after: always; page-break-after: always;
} }
.ellipsize {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}

View File

@ -1,6 +1,6 @@
html { html {
font-family: "Roboto"; font-family: "Roboto";
margin-top: -7px; margin-top: -6px;
} }
* { * {
box-sizing: border-box; box-sizing: border-box;
@ -9,7 +9,7 @@ html {
} }
#vertical { #vertical {
writing-mode: vertical-rl; writing-mode: vertical-rl;
height: 226px; height: 240px;
margin-left: -13px; margin-left: -13px;
} }
.outline { .outline {
@ -18,6 +18,7 @@ html {
} }
#nickname { #nickname {
font-size: 22px; font-size: 22px;
max-width: 50px;
} }
#agencyDescripton { #agencyDescripton {
font-size: 32px; font-size: 32px;

View File

@ -1,35 +1,36 @@
<report-body v-bind="$props"> <!DOCTYPE html>
<template v-slot:header> <html>
<span></span> <body>
</template> <table v-for="labelData in labelsData" style="break-before: page">
<table v-for="labelData in labelsData">
<tbody> <tbody>
<tr> <tr>
<td rowspan="6"><span id="vertical">{{labelData.levelV}}</span></td> <td rowspan="6"><span id="vertical" class="ellipsize">
<td id="ticketFk">{{labelData.ticketFk}} ⬸ {{labelData.clientFk}}</td> {{labelData.collectionFk ? `${labelData.collectionFk} ~ ${labelData.wagon}-${labelData.level}` : '-'.repeat(23)}}
<td colspan="2" id="shipped">{{labelData.shipped}}</td> </span></td>
<td id="ticketFk">
{{labelData.clientFk ? `${labelData.ticketFk} « ${labelData.clientFk}` : labelData.ticketFk}}
</td>
<td colspan="2" id="shipped">{{labelData.shipped ? labelData.shipped : '---'}}</td>
</tr> </tr>
<tr> <tr>
<td rowspan="3"><div v-html="getBarcode(labelData.ticketFk)" id="barcode"></div></td> <td rowspan="3"><div v-html="getBarcode(labelData.ticketFk)" id="barcode"></div></td>
<td class="outline">{{labelData.workerCode}}</td> <td class="outline">{{labelData.workerCode ? labelData.workerCode : '---'}}</td>
</tr> </tr>
<tr> <tr>
<td class="outline">{{labelData.labelCount}}</td> <td class="outline">{{labelData.labelCount ? labelData.labelCount : 0}}</td>
</tr> </tr>
<tr> <tr>
<td class="outline">{{labelData.size}}</td> <td class="outline">{{labelData.code == 'plant' ? labelData.size + 'cm' : labelData.volume + 'm³'}}</td>
</tr> </tr>
<tr> <tr>
<td><div id="agencyDescripton">{{labelData.agencyDescription}}</div></td> <td><div id="agencyDescripton" class="ellipsize">{{labelData.agencyDescription}}</div></td>
<td id="bold">{{labelData.lineCount}}</td> <td id="bold">{{labelData.lineCount ? labelData.lineCount : 0}}</td>
</tr> </tr>
<tr> <tr>
<td id="nickname">{{labelData.nickName}}</td> <td id="nickname" class="ellipsize">{{labelData.nickName ? labelData.nickName : '---'}}</td>
<td id="bold">{{labelData.agencyHour}}</td> <td id="bold">{{labelData.shipped ? labelData.shippedHour : labelData.zoneHour}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<template v-slot:footer> </body>
<span></span> </html>
</template>
</report-body>

View File

@ -40,7 +40,7 @@ module.exports = {
format: 'code128', format: 'code128',
displayValue: false, displayValue: false,
width: 3.8, width: 3.8,
height: 110, height: 115,
}); });
return xmlSerializer.serializeToString(svgNode); return xmlSerializer.serializeToString(svgNode);
}, },

View File

@ -2,8 +2,8 @@
"width": "10.4cm", "width": "10.4cm",
"height": "4.8cm", "height": "4.8cm",
"margin": { "margin": {
"top": "0cm", "top": "0.3cm",
"right": "0.5cm", "right": "0.6cm",
"bottom": "0cm", "bottom": "0cm",
"left": "0cm" "left": "0cm"
}, },

View File

@ -1,21 +1,23 @@
SELECT c.itemPackingTypeFk, SELECT tc.collectionFk,
CONCAT(tc.collectionFk, ' ', LEFT(cc.code, 4)) color, SUBSTRING('ABCDEFGH', tc.wagon, 1) wagon,
CONCAT(tc.collectionFk, ' ', SUBSTRING('ABCDEFGH',tc.wagon, 1), '-', tc.`level`) levelV, tc.`level`,
tc.ticketFk, t.id ticketFk,
LEFT(COALESCE(et.description, zo.name, am.name),12) agencyDescription, COALESCE(et.description, zo.name, am.name) agencyDescription,
am.name, am.name,
t.clientFk, t.clientFk,
CONCAT(CAST(SUM(sv.volume) AS DECIMAL(5, 2)), '') m3 , CAST(SUM(sv.volume) AS DECIMAL(5, 2)) volume,
CAST(IF(ic.code = 'plant', CONCAT(MAX(i.`size`),' cm'), COUNT(*)) AS CHAR) size, MAX(i.`size`) `size`,
ic.code,
w.code workerCode, w.code workerCode,
tt.labelCount, TIME_FORMAT(t.shipped, '%H:%i') shippedHour,
IF(HOUR(t.shipped), TIME_FORMAT(t.shipped, '%H:%i'), TIME_FORMAT(zo.`hour`, '%H:%i')) agencyHour, TIME_FORMAT(zo.`hour`, '%H:%i') zoneHour,
DATE_FORMAT(t.shipped, '%d/%m/%y') shipped, DATE_FORMAT(t.shipped, '%d/%m/%y') shipped,
COUNT(*) lineCount, t.nickName,
t.nickName tt.labelCount,
COUNT(*) lineCount
FROM vn.ticket t FROM vn.ticket t
JOIN vn.ticketCollection tc ON tc.ticketFk = t.id LEFT JOIN vn.ticketCollection tc ON tc.ticketFk = t.id
JOIN vn.collection c ON c.id = tc.collectionFk LEFT JOIN vn.collection c ON c.id = tc.collectionFk
LEFT JOIN vn.collectionColors cc ON cc.shelve = tc.`level` LEFT JOIN vn.collectionColors cc ON cc.shelve = tc.`level`
AND cc.wagon = tc.wagon AND cc.wagon = tc.wagon
AND cc.trainFk = c.trainFk AND cc.trainFk = c.trainFk
@ -24,12 +26,12 @@ SELECT c.itemPackingTypeFk,
JOIN vn.item i ON i.id = s.itemFk JOIN vn.item i ON i.id = s.itemFk
JOIN vn.itemType it ON it.id = i.typeFk JOIN vn.itemType it ON it.id = i.typeFk
JOIN vn.itemCategory ic ON ic.id = it.categoryFk 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 JOIN vn.agencyMode am ON am.id = t.agencyModeFk
LEFT JOIN vn.ticketTrolley tt ON tt.ticket = t.id LEFT JOIN vn.ticketTrolley tt ON tt.ticket = t.id
LEFT JOIN vn.`zone` zo ON t.zoneFk = zo.id LEFT JOIN vn.`zone` zo ON t.zoneFk = zo.id
LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk
LEFT JOIN vn.expeditionTruck et ON et.id = rm.expeditionTruckFk LEFT JOIN vn.expeditionTruck et ON et.id = rm.expeditionTruckFk
WHERE tc.ticketFk IN (?) WHERE t.id IN (?)
GROUP BY t.id GROUP BY t.id
ORDER BY cc.`code`; ORDER BY cc.`code`;