Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5206-travel-buscadorLateral
gitea/salix/pipeline/head There was a failure building this commit Details

This commit is contained in:
Alexandre Riera 2023-03-27 08:38:35 +02:00
commit 8b4121e021
13 changed files with 120 additions and 75 deletions

View File

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- (Monitor tickets) Muestra un icono al lado de la zona, si el ticket es frágil y se envía por agencia - (Monitor tickets) Muestra un icono al lado de la zona, si el ticket es frágil y se envía por agencia
### Changed ### Changed
- (Envíos -> Extra comunitarios) Se agrupan las entradas del mismo travel. Añadidos campos Referencia y Importe.
- (Envíos -> Índice) Cambiado el buscador superior por uno lateral - (Envíos -> Índice) Cambiado el buscador superior por uno lateral
### Fixed ### Fixed

View File

@ -30,16 +30,23 @@ module.exports = Self => {
const recipient = to.replace('@', ''); const recipient = to.replace('@', '');
if (sender.name != recipient) { if (sender.name != recipient) {
await models.Chat.create({ const chat = await models.Chat.create({
senderFk: sender.id, senderFk: sender.id,
recipient: to, recipient: to,
dated: Date.vnNew(), dated: Date.vnNew(),
checkUserStatus: 0, checkUserStatus: 0,
message: message, message: message,
status: 0, status: 'sending',
attempts: 0 attempts: 0
}); });
try {
await Self.sendMessage(chat.senderFk, chat.recipient, chat.message);
await Self.updateChat(chat, 'sent');
} catch (error) {
await Self.updateChat(chat, 'error', error);
}
return true; return true;
} }

View File

@ -24,18 +24,13 @@ module.exports = Self => {
} }
}); });
Self.sendCheckingPresence = async(ctx, recipientId, message, options) => { Self.sendCheckingPresence = async(ctx, recipientId, message) => {
if (!recipientId) return false; if (!recipientId) return false;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const models = Self.app.models; const models = Self.app.models;
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const sender = await models.Account.findById(userId); const sender = await models.Account.findById(userId, {fields: ['id']});
const recipient = await models.Account.findById(recipientId, null, myOptions); const recipient = await models.Account.findById(recipientId, null);
// Prevent sending messages to yourself // Prevent sending messages to yourself
if (recipientId == userId) return false; if (recipientId == userId) return false;
@ -46,16 +41,23 @@ module.exports = Self => {
if (process.env.NODE_ENV == 'test') if (process.env.NODE_ENV == 'test')
message = `[Test:Environment to user ${userId}] ` + message; message = `[Test:Environment to user ${userId}] ` + message;
await models.Chat.create({ const chat = await models.Chat.create({
senderFk: sender.id, senderFk: sender.id,
recipient: `@${recipient.name}`, recipient: `@${recipient.name}`,
dated: Date.vnNew(), dated: Date.vnNew(),
checkUserStatus: 1, checkUserStatus: 1,
message: message, message: message,
status: 0, status: 'sending',
attempts: 0 attempts: 0
}); });
try {
await Self.sendCheckingUserStatus(chat);
await Self.updateChat(chat, 'sent');
} catch (error) {
await Self.updateChat(chat, 'error', error);
}
return true; return true;
}; };
}; };

View File

@ -3,7 +3,6 @@ module.exports = Self => {
Self.remoteMethodCtx('sendQueued', { Self.remoteMethodCtx('sendQueued', {
description: 'Send a RocketChat message', description: 'Send a RocketChat message',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [],
returns: { returns: {
type: 'object', type: 'object',
root: true root: true
@ -16,14 +15,17 @@ module.exports = Self => {
Self.sendQueued = async() => { Self.sendQueued = async() => {
const models = Self.app.models; const models = Self.app.models;
const maxAttempts = 3;
const sentStatus = 1;
const errorStatus = 2;
const chats = await models.Chat.find({ const chats = await models.Chat.find({
where: { where: {
status: {neq: sentStatus}, status: {
attempts: {lt: maxAttempts} nin: [
'sent',
'sending'
]
},
attempts: {lt: 3}
} }
}); });
@ -31,16 +33,16 @@ module.exports = Self => {
if (chat.checkUserStatus) { if (chat.checkUserStatus) {
try { try {
await Self.sendCheckingUserStatus(chat); await Self.sendCheckingUserStatus(chat);
await updateChat(chat, sentStatus); await Self.updateChat(chat, 'sent');
} catch (error) { } catch (error) {
await updateChat(chat, errorStatus, error); await Self.updateChat(chat, 'error', error);
} }
} else { } else {
try { try {
await Self.sendMessage(chat.senderFk, chat.recipient, chat.message); await Self.sendMessage(chat.senderFk, chat.recipient, chat.message);
await updateChat(chat, sentStatus); await Self.updateChat(chat, 'sent');
} catch (error) { } catch (error) {
await updateChat(chat, errorStatus, error); await Self.updateChat(chat, 'error', error);
} }
} }
} }
@ -128,15 +130,17 @@ module.exports = Self => {
* @param {object} chat - The chat * @param {object} chat - The chat
* @param {string} status - The new status * @param {string} status - The new status
* @param {string} error - The error * @param {string} error - The error
* @param {object} options - Query options
* @return {Promise} - The request promise * @return {Promise} - The request promise
*/ */
async function updateChat(chat, status, error) {
Self.updateChat = async(chat, status, error) => {
return chat.updateAttributes({ return chat.updateAttributes({
status: status, status: status,
attempts: ++chat.attempts, attempts: ++chat.attempts,
error: error error: error
}); });
} };
/** /**
* Returns the current user status on Rocketchat * Returns the current user status on Rocketchat

View File

@ -10,7 +10,7 @@ describe('Chat sendCheckingPresence()', () => {
const chat = { const chat = {
checkUserStatus: 1, checkUserStatus: 1,
status: 0, status: 'pending',
attempts: 0 attempts: 0
}; };
@ -27,7 +27,7 @@ describe('Chat sendCheckingPresence()', () => {
const chat = { const chat = {
checkUserStatus: 0, checkUserStatus: 0,
status: 0, status: 'pending',
attempts: 0 attempts: 0
}; };

View File

@ -0,0 +1,16 @@
ALTER TABLE `vn`.`chat` ADD statusNew enum('pending','sent','error','sending') DEFAULT 'pending' NOT NULL;
UPDATE `vn`.`chat`
SET statusNew = 'pending'
WHERE status = 0;
UPDATE `vn`.`chat`
SET statusNew = 'sent'
WHERE status = 1;
UPDATE `vn`.`chat`
SET statusNew = 'error'
WHERE status = 2;
ALTER TABLE `vn`.`chat` CHANGE status status__ tinyint(1) DEFAULT NULL NULL;
ALTER TABLE `vn`.`chat` CHANGE statusNew status enum('pending','sent','error','sending') CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT 'pending' NOT NULL;

View File

@ -501,7 +501,8 @@ INSERT INTO `vn`.`observationType`(`id`,`description`, `code`)
(3, 'Delivery', 'delivery'), (3, 'Delivery', 'delivery'),
(4, 'SalesPerson', 'salesPerson'), (4, 'SalesPerson', 'salesPerson'),
(5, 'Administrative', 'administrative'), (5, 'Administrative', 'administrative'),
(6, 'Weight', 'weight'); (6, 'Weight', 'weight'),
(7, 'InvoiceOut', 'invoiceOut');
INSERT INTO `vn`.`addressObservation`(`id`,`addressFk`,`observationTypeFk`,`description`) INSERT INTO `vn`.`addressObservation`(`id`,`addressFk`,`observationTypeFk`,`description`)
VALUES VALUES
@ -738,7 +739,9 @@ INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `des
(9, 23, 5, 'care with the dog'), (9, 23, 5, 'care with the dog'),
(10, 23, 4, 'Reclama ticket: 8'), (10, 23, 4, 'Reclama ticket: 8'),
(11, 24, 4, 'Reclama ticket: 7'), (11, 24, 4, 'Reclama ticket: 7'),
(12, 11, 3, 'Delivery after 10am'); (12, 11, 3, 'Delivery after 10am'),
(13, 1, 7, 'observation of ticket one'),
(14, 2, 7, 'observation of ticket two');
-- FIX for state hours on local, inter_afterInsert -- FIX for state hours on local, inter_afterInsert
-- UPDATE vncontrol.inter SET odbc_date = DATE_ADD(util.VN_CURDATE(), INTERVAL -10 SECOND); -- UPDATE vncontrol.inter SET odbc_date = DATE_ADD(util.VN_CURDATE(), INTERVAL -10 SECOND);
@ -2631,8 +2634,8 @@ INSERT INTO `vn`.`supplierAgencyTerm` (`agencyFk`, `supplierFk`, `minimumPackage
INSERT INTO `vn`.`chat` (`senderFk`, `recipient`, `dated`, `checkUserStatus`, `message`, `status`, `attempts`) INSERT INTO `vn`.`chat` (`senderFk`, `recipient`, `dated`, `checkUserStatus`, `message`, `status`, `attempts`)
VALUES VALUES
(1101, '@PetterParker', util.VN_CURDATE(), 1, 'First test message', 0, 0), (1101, '@PetterParker', util.VN_CURDATE(), 1, 'First test message', 0, 'sent'),
(1101, '@PetterParker', util.VN_CURDATE(), 0, 'Second test message', 0, 0); (1101, '@PetterParker', util.VN_CURDATE(), 0, 'Second test message', 0, 'pending');
INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`) INSERT INTO `vn`.`mobileAppVersionControl` (`appName`, `version`, `isVersionCritical`)

View File

@ -1,7 +1,7 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const buildFilter = require('vn-loopback/util/filter').buildFilter; const buildFilter = require('vn-loopback/util/filter').buildFilter;
const {mergeFilters, mergeWhere} = require('vn-loopback/util/filter'); const { mergeFilters, mergeWhere } = require('vn-loopback/util/filter');
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('logs', { Self.remoteMethodCtx('logs', {
@ -12,27 +12,27 @@ module.exports = Self => {
arg: 'id', arg: 'id',
type: 'Number', type: 'Number',
description: 'The claim id', description: 'The claim id',
http: {source: 'path'} http: { source: 'path' }
}, },
{ {
arg: 'filter', arg: 'filter',
type: 'object', type: 'object',
http: {source: 'query'} http: { source: 'query' }
}, },
{ {
arg: 'search', arg: 'search',
type: 'string', type: 'string',
http: {source: 'query'} http: { source: 'query' }
}, },
{ {
arg: 'userFk', arg: 'userFk',
type: 'number', type: 'number',
http: {source: 'query'} http: { source: 'query' }
}, },
{ {
arg: 'created', arg: 'created',
type: 'date', type: 'date',
http: {source: 'query'} http: { source: 'query' }
}, },
], ],
returns: { returns: {
@ -45,7 +45,7 @@ module.exports = Self => {
} }
}); });
Self.logs = async(ctx, id, filter, options) => { Self.logs = async (ctx, id, filter, options) => {
const conn = Self.dataSource.connector; const conn = Self.dataSource.connector;
const args = ctx.args; const args = ctx.args;
const myOptions = {}; const myOptions = {};
@ -59,22 +59,22 @@ module.exports = Self => {
case 'search': case 'search':
return { return {
or: [ or: [
{changedModel: {like: `%${value}%`}}, { changedModel: { like: `%${value}%` } },
{oldInstance: {like: `%${value}%`}} { oldInstance: { like: `%${value}%` } }
] ]
}; };
case 'userFk': case 'userFk':
return {'cl.userFk': value}; return { 'cl.userFk': value };
case 'created': case 'created':
value.setHours(0, 0, 0, 0); value.setHours(0, 0, 0, 0);
to = new Date(value); to = new Date(value);
to.setHours(23, 59, 59, 999); to.setHours(23, 59, 59, 999);
return {creationDate: {between: [value, to]}}; return { creationDate: { between: [value, to] } };
} }
}); });
where = mergeWhere(where, {['cl.originFk']: id}); where = mergeWhere(where, { ['cl.originFk']: id });
filter = mergeFilters(args.filter, {where}); filter = mergeFilters(args.filter, { where });
const stmts = []; const stmts = [];
@ -102,8 +102,8 @@ module.exports = Self => {
const logs = []; const logs = [];
for (const row of result) { for (const row of result) {
const changes = []; const changes = [];
const oldInstance = JSON.parse(row.oldInstance); const oldInstance = JSON.parse(row.oldInstance) || {};
const newInstance = JSON.parse(row.newInstance); const newInstance = JSON.parse(row.newInstance) || {};
const mergedProperties = [...Object.keys(oldInstance), ...Object.keys(newInstance)]; const mergedProperties = [...Object.keys(oldInstance), ...Object.keys(newInstance)];
const properties = new Set(mergedProperties); const properties = new Set(mergedProperties);
for (const property of properties) { for (const property of properties) {

View File

@ -130,6 +130,7 @@ module.exports = Self => {
SUM(b.stickers) AS stickers, SUM(b.stickers) AS stickers,
s.id AS cargoSupplierFk, s.id AS cargoSupplierFk,
s.nickname AS cargoSupplierNickname, s.nickname AS cargoSupplierNickname,
s.name AS supplierName,
CAST(SUM(b.weight * b.stickers) as DECIMAL(10,0)) as loadedKg, CAST(SUM(b.weight * b.stickers) as DECIMAL(10,0)) as loadedKg,
CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) as DECIMAL(10,0)) as volumeKg CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) as DECIMAL(10,0)) as volumeKg
FROM travel t FROM travel t
@ -167,6 +168,7 @@ module.exports = Self => {
SUM(b.stickers) AS stickers, SUM(b.stickers) AS stickers,
e.evaNotes, e.evaNotes,
e.notes, e.notes,
e.invoiceAmount,
CAST(SUM(b.weight * b.stickers) AS DECIMAL(10,0)) as loadedkg, CAST(SUM(b.weight * b.stickers) AS DECIMAL(10,0)) as loadedkg,
CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) AS DECIMAL(10,0)) as volumeKg CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) AS DECIMAL(10,0)) as volumeKg
FROM tmp.travel tr FROM tmp.travel tr

View File

@ -3,7 +3,7 @@
url="Travels/extraCommunityFilter" url="Travels/extraCommunityFilter"
user-params="::$ctrl.defaultFilter" user-params="::$ctrl.defaultFilter"
data="travels" data="travels"
order="shipped ASC, landed ASC, travelFk, loadPriority, agencyModeFk, evaNotes" order="landed ASC, shipped ASC, travelFk, loadPriority, agencyModeFk, supplierName, evaNotes"
limit="20" limit="20"
auto-load="true"> auto-load="true">
</vn-crud-model> </vn-crud-model>
@ -48,6 +48,9 @@
<th field="agencyModeFk"> <th field="agencyModeFk">
<span translate>Agency</span> <span translate>Agency</span>
</th> </th>
<th field="invoiceAmount">
<span translate>Amount</span>
</th>
<th field="ref"> <th field="ref">
<span translate>Reference</span> <span translate>Reference</span>
</th> </th>
@ -107,6 +110,7 @@
{{::travel.cargoSupplierNickname}} {{::travel.cargoSupplierNickname}}
</span> </span>
</td> </td>
<td></td>
<td>{{::travel.agencyModeName}}</td> <td>{{::travel.agencyModeName}}</td>
<td vn-click-stop> <td vn-click-stop>
<vn-td-editable name="reference" expand> <vn-td-editable name="reference" expand>
@ -157,22 +161,15 @@
{{::entry.supplierName}} {{::entry.supplierName}}
</span> </span>
</td> </td>
<td number>{{::entry.invoiceAmount | currency: 'EUR': 2}}</td>
<td></td> <td></td>
<td class="td-editable">{{::entry.ref}}</td> <td class="td-editable">{{::entry.invoiceNumber}}</td>
<td number>{{::entry.stickers}}</td> <td number>{{::entry.stickers}}</td>
<td number></td> <td number></td>
<td number>{{::entry.loadedkg}}</td> <td number>{{::entry.loadedkg}}</td>
<td number>{{::entry.volumeKg}}</td> <td number>{{::entry.volumeKg}}</td>
<td> <td></td>
<span ng-if="::entry.notes" vn-tooltip="{{::entry.notes}}"> <td></td>
{{::entry.notes}}
</span>
</td>
<td>
<span ng-if="::entry.evaNotes" vn-tooltip="{{::entry.evaNotes}}">
{{::entry.evaNotes}}
</span>
</td>
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>

View File

@ -240,14 +240,19 @@
</tfoot> </tfoot>
</table> </table>
</div> </div>
<div class="columns vn-mt-xl" v-if="invoice.payMethodCode == 'wireTransfer'"> <div class="columns vn-mt-xl" v-if="invoice.payMethodCode == 'wireTransfer' || ticketObservations">
<div class="size50 pull-left no-page-break"> <div class="size50 pull-left no-page-break">
<div class="panel"> <div class="panel">
<div class="header">{{$t('observations')}}</div> <div class="header">{{$t('observations')}}</div>
<div class="body"> <div class="body">
<div v-if="invoice.payMethodCode == 'wireTransfer'">
<div>{{$t('wireTransfer')}}</div> <div>{{$t('wireTransfer')}}</div>
<div>{{$t('accountNumber', [invoice.iban])}}</div> <div>{{$t('accountNumber', [invoice.iban])}}</div>
</div> </div>
<div v-if="ticketObservations">
{{ticketObservations}}
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -21,11 +21,15 @@ module.exports = {
const map = new Map(); const map = new Map();
this.ticketObservations = '';
for (let ticket of tickets) { for (let ticket of tickets) {
ticket.sales = []; ticket.sales = [];
map.set(ticket.id, ticket); map.set(ticket.id, ticket);
if (ticket.description) this.ticketObservations += ticket.description + ' ';
} }
this.ticketObservations = this.ticketObservations.trim();
for (let sale of sales) { for (let sale of sales) {
const ticket = map.get(sale.ticketFk); const ticket = map.get(sale.ticketFk);

View File

@ -1,8 +1,12 @@
SELECT SELECT
t.id, t.id,
t.shipped, t.shipped,
t.nickname t.nickname,
tto.description
FROM invoiceOut io FROM invoiceOut io
JOIN ticket t ON t.refFk = io.ref JOIN ticket t ON t.refFk = io.REF
LEFT JOIN observationType ot ON ot.code = 'invoiceOut'
LEFT JOIN ticketObservation tto ON tto.ticketFk = t.id
AND tto.observationTypeFk = ot.id
WHERE t.refFk = ? WHERE t.refFk = ?
ORDER BY t.shipped ORDER BY t.shipped