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`
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

View File

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

View File

@ -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':

View File

@ -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 = {};

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,
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

View File

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

View File

@ -49,4 +49,10 @@
.page-break-after {
page-break-after: always;
}
.ellipsize {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}

View File

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

View File

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

View File

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

View File

@ -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"
},

View File

@ -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)), '') 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`;