Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 4859-export_db
This commit is contained in:
commit
67cf4ebbea
|
@ -51,7 +51,7 @@ module.exports = Self => {
|
||||||
const dstFile = path.join(dmsContainer.client.root, pathHash, dms.file);
|
const dstFile = path.join(dmsContainer.client.root, pathHash, dms.file);
|
||||||
await fs.unlink(dstFile);
|
await fs.unlink(dstFile);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.code != 'ENOENT')
|
if (err.code != 'ENOENT' && dms.file)
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2569,10 +2569,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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -91,7 +91,18 @@ 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 'phone':
|
||||||
|
return {or: [
|
||||||
|
{'c.phone': {like: `%${value}%`}},
|
||||||
|
{'c.mobile': {like: `%${value}%`}},
|
||||||
|
]};
|
||||||
|
case 'zoneFk':
|
||||||
|
param = 'a.postalCode';
|
||||||
|
return {[param]: {inq: postalCode}};
|
||||||
case 'name':
|
case 'name':
|
||||||
case 'salesPersonFk':
|
case 'salesPersonFk':
|
||||||
case 'fi':
|
case 'fi':
|
||||||
|
@ -100,12 +111,8 @@ module.exports = Self => {
|
||||||
case 'postcode':
|
case 'postcode':
|
||||||
case 'provinceFk':
|
case 'provinceFk':
|
||||||
case 'email':
|
case 'email':
|
||||||
case 'phone':
|
|
||||||
param = `c.${param}`;
|
param = `c.${param}`;
|
||||||
return {[param]: value};
|
return {[param]: {like: `%${value}%`}};
|
||||||
case 'zoneFk':
|
|
||||||
param = 'a.postalCode';
|
|
||||||
return {[param]: {inq: postalCode}};
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -119,6 +126,7 @@ module.exports = Self => {
|
||||||
c.fi,
|
c.fi,
|
||||||
c.socialName,
|
c.socialName,
|
||||||
c.phone,
|
c.phone,
|
||||||
|
c.mobile,
|
||||||
c.city,
|
c.city,
|
||||||
c.postcode,
|
c.postcode,
|
||||||
c.email,
|
c.email,
|
||||||
|
@ -132,7 +140,7 @@ module.exports = Self => {
|
||||||
LEFT JOIN account.user u ON u.id = c.salesPersonFk
|
LEFT JOIN account.user u ON u.id = c.salesPersonFk
|
||||||
LEFT JOIN province p ON p.id = c.provinceFk
|
LEFT JOIN province p ON p.id = c.provinceFk
|
||||||
JOIN vn.address a ON a.clientFk = c.id
|
JOIN vn.address a ON a.clientFk = c.id
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
|
||||||
stmt.merge(conn.makeWhere(filter.where));
|
stmt.merge(conn.makeWhere(filter.where));
|
||||||
|
|
|
@ -33,36 +33,36 @@ module.exports = Self => {
|
||||||
|
|
||||||
const stmt = new ParameterizedSQL(
|
const stmt = new ParameterizedSQL(
|
||||||
`SELECT
|
`SELECT
|
||||||
t.id,
|
t.id,
|
||||||
t.packages,
|
t.packages,
|
||||||
t.warehouseFk,
|
t.warehouseFk,
|
||||||
t.nickname,
|
t.nickname,
|
||||||
t.clientFk,
|
t.clientFk,
|
||||||
t.priority,
|
t.priority,
|
||||||
t.addressFk,
|
t.addressFk,
|
||||||
st.code AS ticketStateCode,
|
st.code AS ticketStateCode,
|
||||||
st.name AS ticketStateName,
|
st.name AS ticketStateName,
|
||||||
wh.name AS warehouseName,
|
wh.name AS warehouseName,
|
||||||
tob.description AS ticketObservation,
|
tob.description AS ticketObservation,
|
||||||
a.street,
|
a.street,
|
||||||
a.postalCode,
|
a.postalCode,
|
||||||
a.city,
|
a.city,
|
||||||
am.name AS agencyModeName,
|
am.name AS agencyModeName,
|
||||||
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 ticketObservation tob ON tob.ticketFk = t.id
|
LEFT JOIN observationType ot ON ot.code = 'delivery'
|
||||||
LEFT JOIN observationType ot ON tob.observationTypeFk = ot.id
|
LEFT JOIN ticketObservation tob ON tob.ticketFk = t.id
|
||||||
AND ot.code = 'delivery'
|
AND tob.observationTypeFk = ot.id
|
||||||
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
|
||||||
LEFT JOIN vehicle v ON v.id = r.vehicleFk`
|
LEFT JOIN vehicle v ON v.id = r.vehicleFk`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!filter.where) filter.where = {};
|
if (!filter.where) filter.where = {};
|
||||||
|
|
|
@ -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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -332,18 +332,9 @@ module.exports = Self => {
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
const timestamp = started.getTime() / 1000;
|
const timestamp = started.getTime() / 1000;
|
||||||
await models.Mail.create({
|
const url = `${salix.url}worker/${previousWorkerFk}/time-control?timestamp=${timestamp}`;
|
||||||
receiver: previousReceiver,
|
|
||||||
subject: $t('Record of hours week', {
|
|
||||||
week: args.week,
|
|
||||||
year: args.year
|
|
||||||
}),
|
|
||||||
body: `${salix.url}worker/${previousWorkerFk}/time-control?timestamp=${timestamp}`
|
|
||||||
}, myOptions);
|
|
||||||
|
|
||||||
query = `INSERT IGNORE INTO workerTimeControlMail (workerFk, year, week)
|
await models.WorkerTimeControl.weeklyHourRecordEmail(ctx, previousReceiver, args.week, args.year, url);
|
||||||
VALUES (?, ?, ?);`;
|
|
||||||
await Self.rawSql(query, [previousWorkerFk, args.year, args.week], myOptions);
|
|
||||||
|
|
||||||
previousWorkerFk = day.workerFk;
|
previousWorkerFk = day.workerFk;
|
||||||
previousReceiver = day.receiver;
|
previousReceiver = day.receiver;
|
||||||
|
|
|
@ -2,15 +2,12 @@ const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('workerTimeControl sendMail()', () => {
|
describe('workerTimeControl sendMail()', () => {
|
||||||
const workerId = 18;
|
const workerId = 18;
|
||||||
const ctx = {
|
const activeCtx = {
|
||||||
req: {
|
getLocale: () => {
|
||||||
__: value => {
|
return 'en';
|
||||||
return value;
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
args: {}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
const ctx = {req: activeCtx, args: {}};
|
||||||
|
|
||||||
it('should fill time control of a worker without records in Journey and with rest', async() => {
|
it('should fill time control of a worker without records in Journey and with rest', async() => {
|
||||||
const tx = await models.WorkerTimeControl.beginTransaction({});
|
const tx = await models.WorkerTimeControl.beginTransaction({});
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
const {Email} = require('vn-print');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('weeklyHourRecordEmail', {
|
||||||
|
description: 'Sends the buyer waste email',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'recipient',
|
||||||
|
type: 'string',
|
||||||
|
description: 'The recipient email',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'week',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'year',
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'url',
|
||||||
|
type: 'string',
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: '/weekly-hour-hecord-email',
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.weeklyHourRecordEmail = async(ctx, recipient, week, year, url) => {
|
||||||
|
const params = {
|
||||||
|
recipient: recipient,
|
||||||
|
lang: ctx.req.getLocale(),
|
||||||
|
week: week,
|
||||||
|
year: year,
|
||||||
|
url: url
|
||||||
|
};
|
||||||
|
|
||||||
|
const email = new Email('weekly-hour-record', params);
|
||||||
|
|
||||||
|
return email.send();
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
require('../methods/worker-time-control-mail/checkInbox')(Self);
|
||||||
|
};
|
|
@ -7,6 +7,7 @@ module.exports = Self => {
|
||||||
require('../methods/worker-time-control/updateTimeEntry')(Self);
|
require('../methods/worker-time-control/updateTimeEntry')(Self);
|
||||||
require('../methods/worker-time-control/sendMail')(Self);
|
require('../methods/worker-time-control/sendMail')(Self);
|
||||||
require('../methods/worker-time-control/updateWorkerTimeControlMail')(Self);
|
require('../methods/worker-time-control/updateWorkerTimeControlMail')(Self);
|
||||||
|
require('../methods/worker-time-control/weeklyHourRecordEmail')(Self);
|
||||||
|
|
||||||
Self.rewriteDbError(function(err) {
|
Self.rewriteDbError(function(err) {
|
||||||
if (err.code === 'ER_DUP_ENTRY')
|
if (err.code === 'ER_DUP_ENTRY')
|
||||||
|
|
|
@ -49,4 +49,10 @@
|
||||||
|
|
||||||
.page-break-after {
|
.page-break-after {
|
||||||
page-break-after: always;
|
page-break-after: always;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ellipsize {
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
|
@ -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/email.css`])
|
||||||
|
.mergeStyles();
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
subject: Weekly time log
|
||||||
|
title: Record of hours week {0} year {1}
|
||||||
|
dear: Dear worker
|
||||||
|
description: Access the following link:<br/><br/>
|
||||||
|
{0} <br/><br/>
|
||||||
|
Click 'SATISFIED' if you agree with the hours worked. Otherwise, press 'NOT SATISFIED', detailing the cause of the disagreement.
|
|
@ -0,0 +1,6 @@
|
||||||
|
subject: Registro de horas semanal
|
||||||
|
title: Registro de horas semana {0} año {1}
|
||||||
|
dear: Estimado trabajador
|
||||||
|
description: Acceda al siguiente enlace:<br/><br/>
|
||||||
|
{0} <br/><br/>
|
||||||
|
Pulse 'CONFORME' si esta de acuerdo con las horas trabajadas. En caso contrario pulse 'NO CONFORME', detallando la causa de la disconformidad.
|
|
@ -0,0 +1,9 @@
|
||||||
|
<email-body v-bind="$props">
|
||||||
|
<div class="grid-row">
|
||||||
|
<div class="grid-block vn-pa-ml">
|
||||||
|
<h1>{{ $t('title', [week, year]) }}</h1>
|
||||||
|
<p>{{$t('dear')}},</p>
|
||||||
|
<p v-html="$t('description', [url])"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</email-body>
|
|
@ -0,0 +1,23 @@
|
||||||
|
const Component = require(`vn-print/core/component`);
|
||||||
|
const emailBody = new Component('email-body');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
name: 'weekly-hour-record',
|
||||||
|
components: {
|
||||||
|
'email-body': emailBody.build()
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
week: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
year: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -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;
|
||||||
|
|
|
@ -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" class="ellipsize">
|
||||||
<td rowspan="6"><span id="vertical">{{labelData.levelV}}</span></td>
|
{{labelData.collectionFk ? `${labelData.collectionFk} ~ ${labelData.wagon}-${labelData.level}` : '-'.repeat(23)}}
|
||||||
<td id="ticketFk">{{labelData.ticketFk}} ⬸ {{labelData.clientFk}}</td>
|
</span></td>
|
||||||
<td colspan="2" id="shipped">{{labelData.shipped}}</td>
|
<td id="ticketFk">
|
||||||
</tr>
|
{{labelData.clientFk ? `${labelData.ticketFk} « ${labelData.clientFk}` : labelData.ticketFk}}
|
||||||
<tr>
|
</td>
|
||||||
<td rowspan="3"><div v-html="getBarcode(labelData.ticketFk)" id="barcode"></div></td>
|
<td colspan="2" id="shipped">{{labelData.shipped ? labelData.shipped : '---'}}</td>
|
||||||
<td class="outline">{{labelData.workerCode}}</td>
|
</tr>
|
||||||
</tr>
|
<tr>
|
||||||
<tr>
|
<td rowspan="3"><div v-html="getBarcode(labelData.ticketFk)" id="barcode"></div></td>
|
||||||
<td class="outline">{{labelData.labelCount}}</td>
|
<td class="outline">{{labelData.workerCode ? labelData.workerCode : '---'}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="outline">{{labelData.size}}</td>
|
<td class="outline">{{labelData.labelCount ? labelData.labelCount : 0}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><div id="agencyDescripton">{{labelData.agencyDescription}}</div></td>
|
<td class="outline">{{labelData.code == 'plant' ? labelData.size + 'cm' : labelData.volume + 'm³'}}</td>
|
||||||
<td id="bold">{{labelData.lineCount}}</td>
|
</tr>
|
||||||
</tr>
|
<tr>
|
||||||
<tr>
|
<td><div id="agencyDescripton" class="ellipsize">{{labelData.agencyDescription}}</div></td>
|
||||||
<td id="nickname">{{labelData.nickName}}</td>
|
<td id="bold">{{labelData.lineCount ? labelData.lineCount : 0}}</td>
|
||||||
<td id="bold">{{labelData.agencyHour}}</td>
|
</tr>
|
||||||
</tr>
|
<tr>
|
||||||
</tbody>
|
<td id="nickname" class="ellipsize">{{labelData.nickName ? labelData.nickName : '---'}}</td>
|
||||||
</table>
|
<td id="bold">{{labelData.shipped ? labelData.shippedHour : labelData.zoneHour}}</td>
|
||||||
<template v-slot:footer>
|
</tr>
|
||||||
<span></span>
|
</tbody>
|
||||||
</template>
|
</table>
|
||||||
</report-body>
|
</body>
|
||||||
|
</html>
|
|
@ -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);
|
||||||
},
|
},
|
||||||
|
|
|
@ -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"
|
||||||
},
|
},
|
||||||
|
|
|
@ -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)), 'm³') 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`;
|
Loading…
Reference in New Issue