fixes #4074 Descargar ACL del usuario actual #1255
|
@ -4,5 +4,7 @@
|
||||||
"files.eol": "\n",
|
"files.eol": "\n",
|
||||||
"editor.codeActionsOnSave": {
|
"editor.codeActionsOnSave": {
|
||||||
"source.fixAll.eslint": true
|
"source.fixAll.eslint": true
|
||||||
}
|
},
|
||||||
|
"search.useIgnoreFiles": false,
|
||||||
|
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
||||||
}
|
}
|
||||||
|
|
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -5,13 +5,21 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [2312.01] - 2023-04-06
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- (Monitor tickets) Muestra un icono al lado de la zona, si el ticket es frágil y se envía por agencia
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- (Envíos -> Extra comunitarios) Se agrupan las entradas del mismo travel. Añadidos campos Referencia y Importe.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
-
|
||||||
|
|
||||||
## [2310.01] - 2023-03-23
|
## [2310.01] - 2023-03-23
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
-
|
- (Trabajadores -> Control de horario) Ahora se puede confirmar/no confirmar el registro horario de cada semana desde esta sección
|
||||||
|
|
||||||
### Changed
|
|
||||||
-
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- (Clientes -> Listado extendido) Resuelto error al filtrar por clientes inactivos desde la columna "Activo"
|
- (Clientes -> Listado extendido) Resuelto error al filtrar por clientes inactivos desde la columna "Activo"
|
||||||
|
|
|
@ -10,6 +10,7 @@ RUN apt-get update \
|
||||||
curl \
|
curl \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
gnupg2 \
|
gnupg2 \
|
||||||
|
graphicsmagick \
|
||||||
&& curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \
|
&& curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \
|
||||||
&& apt-get install -y --no-install-recommends nodejs \
|
&& apt-get install -y --no-install-recommends nodejs \
|
||||||
&& npm install -g npm@8.19.2
|
&& npm install -g npm@8.19.2
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Report} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('previousLabel', {
|
Self.remoteMethodCtx('previousLabel', {
|
||||||
description: 'Returns the previa label pdf',
|
description: 'Returns the previa label pdf',
|
||||||
|
@ -33,17 +31,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.previousLabel = async(ctx, id) => {
|
Self.previousLabel = (ctx, id) => Self.printReport(ctx, id, 'previa-label');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const report = new Report('previa-label', params);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
|
|
||||||
return [stream, 'application/pdf', `filename="previa-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,21 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('setSaleQuantity()', () => {
|
describe('setSaleQuantity()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should change quantity sale', async() => {
|
it('should change quantity sale', async() => {
|
||||||
const tx = await models.Ticket.beginTransaction({});
|
const tx = await models.Ticket.beginTransaction({});
|
||||||
|
|
||||||
|
|
|
@ -1,215 +0,0 @@
|
||||||
const md5 = require('md5');
|
|
||||||
const fs = require('fs-extra');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
|
||||||
Self.remoteMethodCtx('saveSign', {
|
|
||||||
description: 'Save sign',
|
|
||||||
accessType: 'WRITE',
|
|
||||||
accepts:
|
|
||||||
[
|
|
||||||
{
|
|
||||||
arg: 'signContent',
|
|
||||||
type: 'string',
|
|
||||||
required: true,
|
|
||||||
description: 'The sign content'
|
|
||||||
}, {
|
|
||||||
arg: 'tickets',
|
|
||||||
type: ['number'],
|
|
||||||
required: true,
|
|
||||||
description: 'The tickets'
|
|
||||||
}, {
|
|
||||||
arg: 'signedTime',
|
|
||||||
type: 'date',
|
|
||||||
description: 'The signed time'
|
|
||||||
}, {
|
|
||||||
arg: 'addressFk',
|
|
||||||
type: 'number',
|
|
||||||
required: true,
|
|
||||||
description: 'The address fk'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
returns: {
|
|
||||||
type: 'Object',
|
|
||||||
root: true
|
|
||||||
},
|
|
||||||
http: {
|
|
||||||
path: `/saveSign`,
|
|
||||||
verb: 'POST'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
async function createGestDoc(ticketId, userFk) {
|
|
||||||
const models = Self.app.models;
|
|
||||||
if (!await gestDocExists(ticketId)) {
|
|
||||||
const result = await models.Ticket.findOne({
|
|
||||||
where: {
|
|
||||||
id: ticketId
|
|
||||||
},
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'warehouse',
|
|
||||||
scope: {
|
|
||||||
fields: ['id']
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'client',
|
|
||||||
scope: {
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'route',
|
|
||||||
scope: {
|
|
||||||
fields: ['id']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const warehouseFk = result.warehouseFk;
|
|
||||||
const companyFk = result.companyFk;
|
|
||||||
const client = result.client.name;
|
|
||||||
const route = result.route.id;
|
|
||||||
|
|
||||||
const resultDmsType = await models.DmsType.findOne({
|
|
||||||
where: {
|
|
||||||
code: 'Ticket'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const resultDms = await models.Dms.create({
|
|
||||||
dmsTypeFk: resultDmsType.id,
|
|
||||||
reference: ticketId,
|
|
||||||
description: `Ticket ${ticketId} Cliente ${client} Ruta ${route}`,
|
|
||||||
companyFk: companyFk,
|
|
||||||
warehouseFk: warehouseFk,
|
|
||||||
workerFk: userFk
|
|
||||||
});
|
|
||||||
|
|
||||||
return resultDms.insertId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function gestDocExists(ticket) {
|
|
||||||
const models = Self.app.models;
|
|
||||||
const result = await models.TicketDms.findOne({
|
|
||||||
where: {
|
|
||||||
ticketFk: ticket
|
|
||||||
},
|
|
||||||
fields: ['dmsFk']
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const isSigned = await models.Ticket.findOne({
|
|
||||||
where: {
|
|
||||||
id: ticket
|
|
||||||
},
|
|
||||||
fields: ['isSigned']
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isSigned)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
await models.Dms.destroyById(ticket);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function dmsRecover(ticket, signContent) {
|
|
||||||
const models = Self.app.models;
|
|
||||||
await models.DmsRecover.create({
|
|
||||||
ticketFk: ticket,
|
|
||||||
sign: signContent
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ticketGestdoc(ticket, dmsFk) {
|
|
||||||
const models = Self.app.models;
|
|
||||||
models.TicketDms.replaceOrCreate({
|
|
||||||
ticketFk: ticket,
|
|
||||||
dmsFk: dmsFk
|
|
||||||
});
|
|
||||||
|
|
||||||
const queryVnTicketSetState = `CALL vn.ticket_setState(?, ?)`;
|
|
||||||
|
|
||||||
await Self.rawSql(queryVnTicketSetState, [ticket, 'DELIVERED']);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateGestdoc(file, ticket) {
|
|
||||||
const models = Self.app.models;
|
|
||||||
models.Dms.updateOne({
|
|
||||||
where: {
|
|
||||||
id: ticket
|
|
||||||
},
|
|
||||||
file: file,
|
|
||||||
contentType: 'image/png'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Self.saveSign = async(ctx, signContent, tickets, signedTime) => {
|
|
||||||
const models = Self.app.models;
|
|
||||||
let tx = await Self.beginTransaction({});
|
|
||||||
try {
|
|
||||||
const userId = ctx.req.accessToken.userId;
|
|
||||||
|
|
||||||
const dmsDir = `storage/dms`;
|
|
||||||
|
|
||||||
let image = null;
|
|
||||||
|
|
||||||
for (let i = 0; i < tickets.length; i++) {
|
|
||||||
const alertLevel = await models.TicketState.findOne({
|
|
||||||
where: {
|
|
||||||
ticketFk: tickets[i]
|
|
||||||
},
|
|
||||||
fields: ['alertLevel']
|
|
||||||
});
|
|
||||||
|
|
||||||
signedTime ? signedTime != undefined : signedTime = Date.vnNew();
|
|
||||||
|
|
||||||
if (alertLevel >= 2) {
|
|
||||||
let dir;
|
|
||||||
let id = null;
|
|
||||||
let fileName = null;
|
|
||||||
|
|
||||||
if (!await gestDocExists(tickets[i])) {
|
|
||||||
id = await createGestDoc(tickets[i], userId);
|
|
||||||
|
|
||||||
const hashDir = md5(id).substring(0, 3);
|
|
||||||
dir = `${dmsDir}/${hashDir}`;
|
|
||||||
|
|
||||||
if (!fs.existsSync(dir))
|
|
||||||
fs.mkdirSync(dir);
|
|
||||||
|
|
||||||
fileName = `${id}.png`;
|
|
||||||
image = `${dir}/${fileName}`;
|
|
||||||
} else
|
|
||||||
|
|
||||||
if (image != null) {
|
|
||||||
if (!fs.existsSync(dir))
|
|
||||||
dmsRecover(tickets[i], signContent);
|
|
||||||
else {
|
|
||||||
fs.writeFile(image, signContent, 'base64', async function(err) {
|
|
||||||
if (err) {
|
|
||||||
await tx.rollback();
|
|
||||||
return err.message;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
dmsRecover(tickets[i], signContent);
|
|
||||||
|
|
||||||
if (id != null && fileName.length > 0) {
|
|
||||||
ticketGestdoc(tickets[i], id);
|
|
||||||
updateGestdoc(id, fileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
|
||||||
|
|
||||||
return 'OK';
|
|
||||||
} catch (err) {
|
|
||||||
await tx.rollback();
|
|
||||||
throw err.message;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -132,7 +132,7 @@ module.exports = Self => {
|
||||||
WHERE u.id = ?`, [userId], options);
|
WHERE u.id = ?`, [userId], options);
|
||||||
|
|
||||||
let roles = [];
|
let roles = [];
|
||||||
for (role of result)
|
for (const role of result)
|
||||||
roles.push(role.name);
|
roles.push(role.name);
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
|
|
|
@ -9,17 +9,29 @@
|
||||||
"properties": {
|
"properties": {
|
||||||
"id": {
|
"id": {
|
||||||
"id": true,
|
"id": true,
|
||||||
"type": "number",
|
"type": "number"
|
||||||
"forceId": false
|
|
||||||
},
|
},
|
||||||
"date": {
|
"created": {
|
||||||
"type": "date"
|
"type": "date"
|
||||||
},
|
},
|
||||||
"m3":{
|
"longitude":{
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
"warehouseFk":{
|
"latitude":{
|
||||||
"type": "number"
|
"type": "number"
|
||||||
|
},
|
||||||
|
"dated":{
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"ticketFk":{
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"ticket": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Ticket",
|
||||||
|
"foreignKey": "ticketFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ module.exports = Self => {
|
||||||
require('../methods/dms/removeFile')(Self);
|
require('../methods/dms/removeFile')(Self);
|
||||||
require('../methods/dms/updateFile')(Self);
|
require('../methods/dms/updateFile')(Self);
|
||||||
require('../methods/dms/deleteTrashFiles')(Self);
|
require('../methods/dms/deleteTrashFiles')(Self);
|
||||||
require('../methods/dms/saveSign')(Self);
|
|
||||||
|
|
||||||
Self.checkRole = async function(ctx, id) {
|
Self.checkRole = async function(ctx, id) {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
DROP TABLE `vn`.`dmsRecover`;
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`delivery` DROP FOREIGN KEY delivery_FK;
|
||||||
|
ALTER TABLE `vn`.`delivery` DROP COLUMN addressFk;
|
||||||
|
ALTER TABLE `vn`.`delivery` ADD ticketFk INT NOT NULL;
|
||||||
|
ALTER TABLE `vn`.`delivery` ADD CONSTRAINT delivery_ticketFk_FK FOREIGN KEY (`ticketFk`) REFERENCES `vn`.`ticket`(`id`);
|
||||||
|
|
||||||
|
DELETE FROM `salix`.`ACL` WHERE `property` = 'saveSign';
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalId`)
|
||||||
|
VALUES
|
||||||
|
('Ticket','saveSign','WRITE','ALLOW','employee');
|
||||||
|
|
||||||
|
DROP PROCEDURE IF EXISTS vn.route_getTickets;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`route_getTickets`(vRouteFk INT)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Pasado un RouteFk devuelve la información
|
||||||
|
* de sus tickets.
|
||||||
|
*
|
||||||
|
* @param vRouteFk
|
||||||
|
*
|
||||||
|
* @select Información de los tickets
|
||||||
|
*/
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
t.id Id,
|
||||||
|
t.clientFk Client,
|
||||||
|
a.id Address,
|
||||||
|
t.packages Packages,
|
||||||
|
a.street AddressName,
|
||||||
|
a.postalCode PostalCode,
|
||||||
|
a.city City,
|
||||||
|
sub2.itemPackingTypeFk PackingType,
|
||||||
|
c.phone ClientPhone,
|
||||||
|
c.mobile ClientMobile,
|
||||||
|
a.phone AddressPhone,
|
||||||
|
a.mobile AddressMobile,
|
||||||
|
d.longitude Longitude,
|
||||||
|
d.latitude Latitude,
|
||||||
|
wm.mediaValue SalePersonPhone,
|
||||||
|
tob.Note Note,
|
||||||
|
t.isSigned Signed
|
||||||
|
FROM ticket t
|
||||||
|
JOIN client c ON t.clientFk = c.id
|
||||||
|
JOIN address a ON t.addressFk = a.id
|
||||||
|
LEFT JOIN delivery d ON t.id = d.ticketFk
|
||||||
|
LEFT JOIN workerMedia wm ON wm.workerFk = c.salesPersonFk
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT tob.description Note, t.id
|
||||||
|
FROM ticketObservation tob
|
||||||
|
JOIN ticket t ON tob.ticketFk = t.id
|
||||||
|
JOIN observationType ot ON ot.id = tob.observationTypeFk
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
AND ot.code = 'delivery'
|
||||||
|
)tob ON tob.id = t.id
|
||||||
|
LEFT JOIN
|
||||||
|
(SELECT sub.ticketFk,
|
||||||
|
CONCAT('(', GROUP_CONCAT(DISTINCT sub.itemPackingTypeFk ORDER BY sub.items DESC SEPARATOR ','), ') ') itemPackingTypeFk
|
||||||
|
FROM (SELECT s.ticketFk , i.itemPackingTypeFk, COUNT(*) items
|
||||||
|
FROM ticket t
|
||||||
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
GROUP BY t.id,i.itemPackingTypeFk)sub
|
||||||
|
GROUP BY sub.ticketFk
|
||||||
|
) sub2 ON sub2.ticketFk = t.id
|
||||||
|
WHERE t.routeFk = vRouteFk
|
||||||
|
GROUP BY t.id
|
||||||
|
ORDER BY t.priority;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,6 @@
|
||||||
|
ALTER TABLE vn.invoiceOutSerial
|
||||||
|
ADD `type` ENUM('global', 'quick') DEFAULT NULL NULL;
|
||||||
|
|
||||||
|
UPDATE vn.invoiceOutSerial
|
||||||
|
SET type = 'global'
|
||||||
|
WHERE code IN ('A','V');
|
|
@ -2,13 +2,15 @@ DROP FUNCTION IF EXISTS `vn`.`invoiceOut_getWeight`;
|
||||||
|
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
$$
|
$$
|
||||||
CREATE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceOut_getWeight`(vInvoice VARCHAR(15)) RETURNS decimal(10,2)
|
CREATE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceOut_getWeight`(
|
||||||
|
vInvoiceRef VARCHAR(15)
|
||||||
|
)RETURNS decimal(10,2)
|
||||||
READS SQL DATA
|
READS SQL DATA
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Calcula el peso de una factura emitida
|
* Calcula el peso de una factura emitida
|
||||||
*
|
*
|
||||||
* @param vInvoice Id de la factura
|
* @param vInvoiceRef referencia de la factura
|
||||||
* @return vTotalWeight peso de la factura
|
* @return vTotalWeight peso de la factura
|
||||||
*/
|
*/
|
||||||
DECLARE vTotalWeight DECIMAL(10,2);
|
DECLARE vTotalWeight DECIMAL(10,2);
|
||||||
|
@ -22,7 +24,7 @@ BEGIN
|
||||||
JOIN item i ON i.id = s.itemFk
|
JOIN item i ON i.id = s.itemFk
|
||||||
JOIN itemCost ic ON ic.itemFk = i.id
|
JOIN itemCost ic ON ic.itemFk = i.id
|
||||||
AND ic.warehouseFk = t.warehouseFk
|
AND ic.warehouseFk = t.warehouseFk
|
||||||
WHERE t.refFk = vInvoice
|
WHERE t.refFk = vInvoiceRef
|
||||||
AND i.intrastatFk;
|
AND i.intrastatFk;
|
||||||
|
|
||||||
RETURN vTotalWeight;
|
RETURN vTotalWeight;
|
|
@ -0,0 +1,6 @@
|
||||||
|
UPDATE `vn`.`report`
|
||||||
|
SET `method`='InvoiceOuts/{refFk}/invoice-out-pdf'
|
||||||
|
WHERE name='invoice';
|
||||||
|
|
||||||
|
ALTER TABLE `vn`.`printQueue` MODIFY COLUMN printerFk tinyint(3) unsigned DEFAULT 82 NOT NULL;
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
DROP FUNCTION IF EXISTS `vn`.`invoiceOut_getMaxIssued`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceOut_getMaxIssued`(
|
||||||
|
vSerial VARCHAR(2),
|
||||||
|
vCompanyFk INT,
|
||||||
|
vYear INT
|
||||||
|
) RETURNS DATE
|
||||||
|
READS SQL DATA
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Retorna la fecha a partir de la cual es válido emitir una factura
|
||||||
|
*
|
||||||
|
* @param vSerial Serie de facturación
|
||||||
|
* @param vCompanyFk Empresa factura emitida
|
||||||
|
* @param vYear Año contable
|
||||||
|
* @return vInvoiceOutIssued fecha factura válida
|
||||||
|
*/
|
||||||
|
DECLARE vInvoiceOutIssued DATE;
|
||||||
|
DECLARE vFirstDayOfYear DATE;
|
||||||
|
|
||||||
|
SET vFirstDayOfYear := MAKEDATE(vYear, 1);
|
||||||
|
|
||||||
|
SELECT IFNULL(MAX(io.issued), vFirstDayOfYear) INTO vInvoiceOutIssued
|
||||||
|
FROM invoiceOut io
|
||||||
|
WHERE io.serial = vSerial
|
||||||
|
AND io.companyFk = vCompanyFk
|
||||||
|
AND io.issued BETWEEN vFirstDayOfYear
|
||||||
|
AND util.lastDayOfYear(vFirstDayOfYear);
|
||||||
|
|
||||||
|
RETURN vInvoiceOutIssued;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,258 @@
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`invoiceOut_new`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`invoiceOut_new`(
|
||||||
|
vSerial VARCHAR(255),
|
||||||
|
vInvoiceDate DATE,
|
||||||
|
vTaxArea VARCHAR(25),
|
||||||
|
OUT vNewInvoiceId INT)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Creación de facturas emitidas.
|
||||||
|
* requiere previamente tabla ticketToInvoice(id).
|
||||||
|
*
|
||||||
|
* @param vSerial serie a la cual se hace la factura
|
||||||
|
* @param vInvoiceDate fecha de la factura
|
||||||
|
* @param vTaxArea tipo de iva en relacion a la empresa y al cliente
|
||||||
|
* @param vNewInvoiceId id de la factura que se acaba de generar
|
||||||
|
* @return vNewInvoiceId
|
||||||
|
*/
|
||||||
|
DECLARE vIsAnySaleToInvoice BOOL;
|
||||||
|
DECLARE vIsAnyServiceToInvoice BOOL;
|
||||||
|
DECLARE vNewRef VARCHAR(255);
|
||||||
|
DECLARE vWorker INT DEFAULT account.myUser_getId();
|
||||||
|
DECLARE vCompanyFk INT;
|
||||||
|
DECLARE vInterCompanyFk INT;
|
||||||
|
DECLARE vClientFk INT;
|
||||||
|
DECLARE vCplusStandardInvoiceTypeFk INT DEFAULT 1;
|
||||||
|
DECLARE vCplusCorrectingInvoiceTypeFk INT DEFAULT 6;
|
||||||
|
DECLARE vCplusSimplifiedInvoiceTypeFk INT DEFAULT 2;
|
||||||
|
DECLARE vCorrectingSerial VARCHAR(1) DEFAULT 'R';
|
||||||
|
DECLARE vSimplifiedSerial VARCHAR(1) DEFAULT 'S';
|
||||||
|
DECLARE vNewInvoiceInFk INT;
|
||||||
|
DECLARE vIsInterCompany BOOL DEFAULT FALSE;
|
||||||
|
DECLARE vIsCEESerial BOOL DEFAULT FALSE;
|
||||||
|
DECLARE vIsCorrectInvoiceDate BOOL;
|
||||||
|
DECLARE vMaxShipped DATE;
|
||||||
|
|
||||||
|
SET vInvoiceDate = IFNULL(vInvoiceDate, util.CURDATE());
|
||||||
|
|
||||||
|
SELECT t.clientFk,
|
||||||
|
t.companyFk,
|
||||||
|
MAX(DATE(t.shipped)),
|
||||||
|
DATE(vInvoiceDate) >= invoiceOut_getMaxIssued(
|
||||||
|
vSerial,
|
||||||
|
t.companyFk,
|
||||||
|
YEAR(vInvoiceDate))
|
||||||
|
INTO vClientFk,
|
||||||
|
vCompanyFk,
|
||||||
|
vMaxShipped,
|
||||||
|
vIsCorrectInvoiceDate
|
||||||
|
FROM ticketToInvoice tt
|
||||||
|
JOIN ticket t ON t.id = tt.id;
|
||||||
|
|
||||||
|
IF(vMaxShipped > vInvoiceDate) THEN
|
||||||
|
CALL util.throw("Invoice date can't be less than max date");
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF NOT vIsCorrectInvoiceDate THEN
|
||||||
|
CALL util.throw('Exists an invoice with a previous date');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Eliminem de ticketToInvoice els tickets que no han de ser facturats
|
||||||
|
DELETE ti.*
|
||||||
|
FROM ticketToInvoice ti
|
||||||
|
JOIN ticket t ON t.id = ti.id
|
||||||
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
JOIN supplier su ON su.id = t.companyFk
|
||||||
|
JOIN client c ON c.id = t.clientFk
|
||||||
|
LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id AND itc.countryFk = su.countryFk
|
||||||
|
WHERE (YEAR(t.shipped) < 2001 AND t.isDeleted)
|
||||||
|
OR c.isTaxDataChecked = FALSE
|
||||||
|
OR t.isDeleted
|
||||||
|
OR c.hasToInvoice = FALSE
|
||||||
|
OR itc.id IS NULL;
|
||||||
|
|
||||||
|
SELECT SUM(s.quantity * s.price * (100 - s.discount)/100) <> 0
|
||||||
|
INTO vIsAnySaleToInvoice
|
||||||
|
FROM ticketToInvoice t
|
||||||
|
JOIN sale s ON s.ticketFk = t.id;
|
||||||
|
|
||||||
|
SELECT COUNT(*) > 0 INTO vIsAnyServiceToInvoice
|
||||||
|
FROM ticketToInvoice t
|
||||||
|
JOIN ticketService ts ON ts.ticketFk = t.id;
|
||||||
|
|
||||||
|
IF (vIsAnySaleToInvoice OR vIsAnyServiceToInvoice)
|
||||||
|
AND (vCorrectingSerial = vSerial OR NOT hasAnyNegativeBase())
|
||||||
|
THEN
|
||||||
|
|
||||||
|
-- el trigger añade el siguiente Id_Factura correspondiente a la vSerial
|
||||||
|
INSERT INTO invoiceOut(
|
||||||
|
ref,
|
||||||
|
serial,
|
||||||
|
issued,
|
||||||
|
clientFk,
|
||||||
|
dued,
|
||||||
|
companyFk,
|
||||||
|
cplusInvoiceType477Fk
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
1,
|
||||||
|
vSerial,
|
||||||
|
vInvoiceDate,
|
||||||
|
vClientFk,
|
||||||
|
getDueDate(vInvoiceDate, dueDay),
|
||||||
|
vCompanyFk,
|
||||||
|
IF(vSerial = vCorrectingSerial,
|
||||||
|
vCplusCorrectingInvoiceTypeFk,
|
||||||
|
IF(vSerial = vSimplifiedSerial,
|
||||||
|
vCplusSimplifiedInvoiceTypeFk,
|
||||||
|
vCplusStandardInvoiceTypeFk))
|
||||||
|
FROM client
|
||||||
|
WHERE id = vClientFk;
|
||||||
|
|
||||||
|
SET vNewInvoiceId = LAST_INSERT_ID();
|
||||||
|
|
||||||
|
SELECT `ref`
|
||||||
|
INTO vNewRef
|
||||||
|
FROM invoiceOut
|
||||||
|
WHERE id = vNewInvoiceId;
|
||||||
|
|
||||||
|
UPDATE ticket t
|
||||||
|
JOIN ticketToInvoice ti ON ti.id = t.id
|
||||||
|
SET t.refFk = vNewRef;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.updateInter;
|
||||||
|
CREATE TEMPORARY TABLE tmp.updateInter ENGINE = MEMORY
|
||||||
|
SELECT s.id,ti.id ticket_id,vWorker Id_Trabajador
|
||||||
|
FROM ticketToInvoice ti
|
||||||
|
LEFT JOIN ticketState ts ON ti.id = ts.ticket
|
||||||
|
JOIN state s
|
||||||
|
WHERE IFNULL(ts.alertLevel,0) < 3 and s.`code` = getAlert3State(ti.id);
|
||||||
|
|
||||||
|
INSERT INTO ticketTracking(stateFk,ticketFk,workerFk)
|
||||||
|
SELECT * FROM tmp.updateInter;
|
||||||
|
|
||||||
|
INSERT INTO ticketLog (action, userFk, originFk, description)
|
||||||
|
SELECT 'UPDATE', account.myUser_getId(), ti.id, CONCAT('Crea factura ', vNewRef)
|
||||||
|
FROM ticketToInvoice ti;
|
||||||
|
|
||||||
|
CALL invoiceExpenceMake(vNewInvoiceId);
|
||||||
|
CALL invoiceTaxMake(vNewInvoiceId,vTaxArea);
|
||||||
|
|
||||||
|
UPDATE invoiceOut io
|
||||||
|
JOIN (
|
||||||
|
SELECT SUM(amount) total
|
||||||
|
FROM invoiceOutExpence
|
||||||
|
WHERE invoiceOutFk = vNewInvoiceId
|
||||||
|
) base
|
||||||
|
JOIN (
|
||||||
|
SELECT SUM(vat) total
|
||||||
|
FROM invoiceOutTax
|
||||||
|
WHERE invoiceOutFk = vNewInvoiceId
|
||||||
|
) vat
|
||||||
|
SET io.amount = base.total + vat.total
|
||||||
|
WHERE io.id = vNewInvoiceId;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE tmp.updateInter;
|
||||||
|
|
||||||
|
SELECT COUNT(*), id
|
||||||
|
INTO vIsInterCompany, vInterCompanyFk
|
||||||
|
FROM company
|
||||||
|
WHERE clientFk = vClientFk;
|
||||||
|
|
||||||
|
IF (vIsInterCompany) THEN
|
||||||
|
|
||||||
|
INSERT INTO invoiceIn(supplierFk, supplierRef, issued, companyFk)
|
||||||
|
SELECT vCompanyFk, vNewRef, vInvoiceDate, vInterCompanyFk;
|
||||||
|
|
||||||
|
SET vNewInvoiceInFk = LAST_INSERT_ID();
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticket;
|
||||||
|
CREATE TEMPORARY TABLE tmp.ticket
|
||||||
|
(KEY (ticketFk))
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT id ticketFk
|
||||||
|
FROM ticketToInvoice;
|
||||||
|
|
||||||
|
CALL `ticket_getTax`('NATIONAL');
|
||||||
|
|
||||||
|
SET @vTaxableBaseServices := 0.00;
|
||||||
|
SET @vTaxCodeGeneral := NULL;
|
||||||
|
|
||||||
|
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk)
|
||||||
|
SELECT vNewInvoiceInFk,
|
||||||
|
@vTaxableBaseServices,
|
||||||
|
sub.expenceFk,
|
||||||
|
sub.taxTypeSageFk,
|
||||||
|
sub.transactionTypeSageFk
|
||||||
|
FROM (
|
||||||
|
SELECT @vTaxableBaseServices := SUM(tst.taxableBase) taxableBase,
|
||||||
|
i.expenceFk,
|
||||||
|
i.taxTypeSageFk,
|
||||||
|
i.transactionTypeSageFk,
|
||||||
|
@vTaxCodeGeneral := i.taxClassCodeFk
|
||||||
|
FROM tmp.ticketServiceTax tst
|
||||||
|
JOIN invoiceOutTaxConfig i ON i.taxClassCodeFk = tst.code
|
||||||
|
WHERE i.isService
|
||||||
|
HAVING taxableBase
|
||||||
|
) sub;
|
||||||
|
|
||||||
|
INSERT INTO invoiceInTax(invoiceInFk, taxableBase, expenceFk, taxTypeSageFk, transactionTypeSageFk)
|
||||||
|
SELECT vNewInvoiceInFk,
|
||||||
|
SUM(tt.taxableBase) - IF(tt.code = @vTaxCodeGeneral,
|
||||||
|
@vTaxableBaseServices, 0) taxableBase,
|
||||||
|
i.expenceFk,
|
||||||
|
i.taxTypeSageFk ,
|
||||||
|
i.transactionTypeSageFk
|
||||||
|
FROM tmp.ticketTax tt
|
||||||
|
JOIN invoiceOutTaxConfig i ON i.taxClassCodeFk = tt.code
|
||||||
|
WHERE !i.isService
|
||||||
|
GROUP BY tt.pgcFk
|
||||||
|
HAVING taxableBase
|
||||||
|
ORDER BY tt.priority;
|
||||||
|
|
||||||
|
CALL invoiceInDueDay_calculate(vNewInvoiceInFk);
|
||||||
|
|
||||||
|
SELECT COUNT(*) INTO vIsCEESerial
|
||||||
|
FROM invoiceOutSerial
|
||||||
|
WHERE code = vSerial;
|
||||||
|
|
||||||
|
IF vIsCEESerial THEN
|
||||||
|
|
||||||
|
INSERT INTO invoiceInIntrastat (
|
||||||
|
invoiceInFk,
|
||||||
|
intrastatFk,
|
||||||
|
amount,
|
||||||
|
stems,
|
||||||
|
countryFk,
|
||||||
|
net)
|
||||||
|
SELECT
|
||||||
|
vNewInvoiceInFk,
|
||||||
|
i.intrastatFk,
|
||||||
|
SUM(CAST((s.quantity * s.price * (100 - s.discount) / 100 ) AS DECIMAL(10, 2))),
|
||||||
|
SUM(CAST(IFNULL(i.stems, 1) * s.quantity AS DECIMAL(10, 2))),
|
||||||
|
su.countryFk,
|
||||||
|
CAST(SUM(IFNULL(i.stems, 1)
|
||||||
|
* s.quantity
|
||||||
|
* IF(ic.grams, ic.grams, IFNULL(i.weightByPiece, 0)) / 1000) AS DECIMAL(10, 2))
|
||||||
|
FROM sale s
|
||||||
|
JOIN ticket t ON s.ticketFk = t.id
|
||||||
|
JOIN supplier su ON su.id = t.companyFk
|
||||||
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
LEFT JOIN itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk
|
||||||
|
WHERE t.refFk = vNewRef
|
||||||
|
GROUP BY i.intrastatFk;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
DROP TEMPORARY TABLE tmp.ticket;
|
||||||
|
DROP TEMPORARY TABLE tmp.ticketAmount;
|
||||||
|
DROP TEMPORARY TABLE tmp.ticketTax;
|
||||||
|
DROP TEMPORARY TABLE tmp.ticketServiceTax;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
DROP TEMPORARY TABLE `ticketToInvoice`;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,141 @@
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`ticketPackaging_add`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticketPackaging_add`(
|
||||||
|
vClientFk INT,
|
||||||
|
vDated DATE,
|
||||||
|
vCompanyFk INT,
|
||||||
|
vWithoutPeriodGrace BOOLEAN)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Genera nuevos tickets de embalajes para los clientes no han los han retornado
|
||||||
|
* y actualiza los valores para la tabla ticketPackaging
|
||||||
|
*
|
||||||
|
* @param vClientFk Cliente en caso de NULL todos los clientes
|
||||||
|
* @param vDated Fecha hasta la cual se revisan los embalajes
|
||||||
|
* @param vCompanyFk Empresa de la cual se comprobaran sus clientes
|
||||||
|
* @param vWithoutPeriodGrace si no se aplica el periodo de gracia de un mes
|
||||||
|
*/
|
||||||
|
DECLARE vNewTicket INT;
|
||||||
|
DECLARE vDateStart DATE;
|
||||||
|
DECLARE vDateEnd DATE;
|
||||||
|
DECLARE vGraceDate DATE DEFAULT vDated;
|
||||||
|
DECLARE vWarehouseInventory INT;
|
||||||
|
DECLARE vComponentCost INT;
|
||||||
|
DECLARE vDone INT DEFAULT FALSE;
|
||||||
|
DECLARE vClientId INT;
|
||||||
|
|
||||||
|
DECLARE vCursor CURSOR FOR
|
||||||
|
SELECT DISTINCT clientFk
|
||||||
|
FROM (
|
||||||
|
SELECT clientFk, SUM(quantity) totalQuantity
|
||||||
|
FROM tmp.packagingToInvoice
|
||||||
|
GROUP BY itemFk, clientFk
|
||||||
|
HAVING totalQuantity > 0)sub;
|
||||||
|
|
||||||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
|
|
||||||
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
ROLLBACK;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
SELECT id INTO vWarehouseInventory
|
||||||
|
FROM warehouse
|
||||||
|
WHERE `code`= 'inv';
|
||||||
|
|
||||||
|
SELECT id INTO vComponentCost
|
||||||
|
FROM component
|
||||||
|
WHERE `code`= 'purchaseValue';
|
||||||
|
|
||||||
|
SELECT packagingInvoicingDated INTO vDateStart
|
||||||
|
FROM ticketConfig;
|
||||||
|
|
||||||
|
IF vWarehouseInventory IS NULL THEN
|
||||||
|
CALL util.throw('Warehouse inventory not set');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF vComponentCost IS NULL THEN
|
||||||
|
CALL util.throw('Component cost not set');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SET vDateEnd = vDated + INTERVAL 1 DAY;
|
||||||
|
|
||||||
|
IF NOT vWithoutPeriodGrace THEN
|
||||||
|
SET vGraceDate = vGraceDate -INTERVAL 1 MONTH;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.packagingToInvoice;
|
||||||
|
CREATE TEMPORARY TABLE tmp.packagingToInvoice
|
||||||
|
(INDEX (clientFk))
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT p.itemFk,
|
||||||
|
tp.packagingFk,
|
||||||
|
tp.quantity,
|
||||||
|
tp.ticketFk,
|
||||||
|
p.price,
|
||||||
|
t.clientFk
|
||||||
|
FROM ticketPackaging tp
|
||||||
|
JOIN packaging p ON p.id = tp.packagingFk
|
||||||
|
JOIN ticket t ON t.id = tp.ticketFk
|
||||||
|
JOIN client c ON c.id = t.clientFk
|
||||||
|
WHERE c.isActive
|
||||||
|
AND (vClientFk IS NULL OR t.clientFk = vClientFk)
|
||||||
|
AND t.shipped BETWEEN vDateStart AND vDateEnd
|
||||||
|
AND (tp.quantity < 0 OR (tp.quantity > 0 AND t.shipped < vGraceDate))
|
||||||
|
AND tp.quantity
|
||||||
|
AND p.itemFk;
|
||||||
|
|
||||||
|
OPEN vCursor;
|
||||||
|
l: LOOP
|
||||||
|
|
||||||
|
FETCH vCursor INTO vClientId;
|
||||||
|
|
||||||
|
IF vDone THEN
|
||||||
|
LEAVE l;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
CALL ticket_add(
|
||||||
|
vClientId,
|
||||||
|
vDateEnd,
|
||||||
|
vWarehouseInventory,
|
||||||
|
vCompanyFk,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
vDateEnd,
|
||||||
|
account.myUser_getId(),
|
||||||
|
TRUE,
|
||||||
|
vNewTicket);
|
||||||
|
|
||||||
|
INSERT INTO ticketPackaging(ticketFk, packagingFk, quantity, pvp)
|
||||||
|
SELECT vNewTicket, packagingFk, - SUM(quantity) totalQuantity, price
|
||||||
|
FROM tmp.packagingToInvoice
|
||||||
|
WHERE clientFk = vClientId
|
||||||
|
GROUP BY packagingFk
|
||||||
|
HAVING IF(vWithoutPeriodGrace, totalQuantity <> 0, totalQuantity < 0);
|
||||||
|
|
||||||
|
INSERT INTO sale(ticketFk, itemFk, concept, quantity, price)
|
||||||
|
SELECT vNewTicket, pti.itemFk, i.name, SUM(pti.quantity) totalQuantity, pti.price
|
||||||
|
FROM tmp.packagingToInvoice pti
|
||||||
|
JOIN item i ON i.id = pti.itemFk
|
||||||
|
WHERE pti.clientFk = vClientId
|
||||||
|
GROUP BY pti.itemFk
|
||||||
|
HAVING IF(vWithoutPeriodGrace, totalQuantity <> 0, totalQuantity > 0);
|
||||||
|
|
||||||
|
INSERT INTO saleComponent(saleFk, componentFk, value)
|
||||||
|
SELECT id, vComponentCost, price
|
||||||
|
FROM sale
|
||||||
|
WHERE ticketFk = vNewTicket;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
END LOOP;
|
||||||
|
CLOSE vCursor;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE tmp.packagingToInvoice;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,3 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES ('Operator', '*', 'READ', 'ALLOW', 'ROLE', 'employee'),
|
||||||
|
('Operator', '*', 'WRITE', 'ALLOW', 'ROLE', 'employee');
|
|
@ -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;
|
|
@ -0,0 +1,14 @@
|
||||||
|
ALTER TABLE `vn`.`itemType` ADD isFragile tinyint(1) NULL;
|
||||||
|
ALTER TABLE `vn`.`itemType` MODIFY COLUMN isFragile tinyint(1) DEFAULT 0 NOT NULL;
|
||||||
|
|
||||||
|
UPDATE `vn`.`itemType`
|
||||||
|
SET isFragile = 1
|
||||||
|
WHERE code IN ('ZKA', 'ZKE');
|
||||||
|
|
||||||
|
UPDATE `vn`.`itemType`
|
||||||
|
SET isFragile = 1
|
||||||
|
WHERE id IN (SELECT it.id
|
||||||
|
FROM itemCategory ic
|
||||||
|
JOIN itemType it ON it.categoryFk = ic.id
|
||||||
|
WHERE ic.code = 'plant');
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
ALTER TABLE `vn`.`operator` ADD sectorFk int(11) NULL;
|
||||||
|
ALTER TABLE `vn`.`operator` ADD labelerFk tinyint(3) unsigned NULL;
|
||||||
|
ALTER TABLE `vn`.`operator` ADD CONSTRAINT operator_FK_5 FOREIGN KEY (labelerFk) REFERENCES `vn`.`printer`(id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
UPDATE `vn`.`operator` o
|
||||||
|
JOIN (SELECT id, sectorFk, labelerFk
|
||||||
|
FROM `vn`.`worker`) sub ON sub.id = o.workerFk
|
||||||
|
SET o.sectorFk = sub.sectorFk,
|
||||||
|
o.labelerFk = sub.labelerFk;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`collection_printSticker`(
|
||||||
|
vSelf INT,
|
||||||
|
vLabelCount INT
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Prints a yellow label from a collection or a ticket
|
||||||
|
*
|
||||||
|
* @param vSelf collection or ticket
|
||||||
|
* @param vLabelCount number of times the collection has been printed
|
||||||
|
*/
|
||||||
|
DECLARE vPrintArgs JSON DEFAULT JSON_OBJECT('collectionOrTicketFk', vSelf);
|
||||||
|
|
||||||
|
IF vLabelCount IS NULL THEN
|
||||||
|
INSERT INTO ticketTrolley
|
||||||
|
SELECT ticketFk, 1
|
||||||
|
FROM ticketCollection
|
||||||
|
WHERE collectionFk = vSelf
|
||||||
|
ON DUPLICATE KEY UPDATE labelCount = labelCount + 1;
|
||||||
|
ELSE
|
||||||
|
SET vPrintArgs = JSON_MERGE_PATCH(vPrintArgs, JSON_OBJECT('labelCount', vLabelCount));
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
CALL report_print(
|
||||||
|
'LabelCollection',
|
||||||
|
(SELECT o.labelerFk FROM operator o WHERE o.workerFk = account.myUser_getId()),
|
||||||
|
account.myUser_getId(),
|
||||||
|
vPrintArgs,
|
||||||
|
'high'
|
||||||
|
);
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`expeditionPallet_printLabel`(vSelf INT)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Calls the report_print procedure and passes it
|
||||||
|
* the necessary parameters for printing.
|
||||||
|
*
|
||||||
|
* @param vSelf expeditioPallet id.
|
||||||
|
*/
|
||||||
|
DECLARE vPrinterFk INT;
|
||||||
|
DECLARE vUserFk INT DEFAULT account.myUser_getId();
|
||||||
|
|
||||||
|
SELECT o.labelerFk INTO vPrinterFk
|
||||||
|
FROM operator o
|
||||||
|
WHERE o.workerFk = vUserFk;
|
||||||
|
|
||||||
|
CALL vn.report_print(
|
||||||
|
'LabelPalletExpedition',
|
||||||
|
vPrinterFk,
|
||||||
|
account.myUser_getId(),
|
||||||
|
JSON_OBJECT('palletFk', vSelf, 'userFk', vUserFk),
|
||||||
|
'high'
|
||||||
|
);
|
||||||
|
|
||||||
|
UPDATE vn.expeditionPallet
|
||||||
|
SET isPrint = TRUE
|
||||||
|
WHERE id = vSelf;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelving_getAlternatives`(vShelvingFk VARCHAR(10))
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Devuelve un listado de posibles ubicaciones alternativas a ubicar los item de la matricula
|
||||||
|
* del carro que se le ha pasado.
|
||||||
|
*
|
||||||
|
* @param vShelvingFk matricula del carro
|
||||||
|
*/
|
||||||
|
SELECT is2.id,is2.shelvingFk , p.code, is2.itemFk , is2.visible, p.pickingOrder
|
||||||
|
FROM itemShelving is2
|
||||||
|
JOIN shelving sh ON sh.code = is2.shelvingFk
|
||||||
|
JOIN parking p ON p.id = sh.parkingFk
|
||||||
|
JOIN sector s ON s.id = p.sectorFk
|
||||||
|
LEFT JOIN operator o ON o.sectorFk = s.id
|
||||||
|
LEFT JOIN worker w ON w.sectorFk = s.id AND w.id = account.myUser_getId()
|
||||||
|
JOIN warehouse wh ON wh.id = s.warehouseFk
|
||||||
|
JOIN itemShelving is3 ON is3.itemFk = is2.itemFk AND is3.shelvingFk = vShelvingFk COLLATE utf8_unicode_ci
|
||||||
|
WHERE is2.shelvingFk <> vShelvingFk COLLATE utf8_unicode_ci
|
||||||
|
GROUP BY is2.id
|
||||||
|
ORDER BY p.pickingOrder DESC;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`operator_beforeInsert`
|
||||||
|
BEFORE INSERT ON `operator`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
CALL vn.printer_checkSector(NEW.labelerFk, NEW.sectorFk);
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`operator_beforeUpdate`
|
||||||
|
BEFORE UPDATE ON `operator`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
IF NOT (NEW.labelerFk <=> OLD.labelerFk AND NEW.sectorFk <=> OLD.sectorFk) THEN
|
||||||
|
CALL vn.printer_checkSector(NEW.labelerFk, NEW.sectorFk);
|
||||||
|
END IF;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`worker_beforeUpdate`
|
||||||
|
BEFORE UPDATE ON `worker`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
IF NOT (NEW.labelerFk <=> OLD.labelerFk AND NEW.sectorFk <=> OLD.sectorFk) THEN
|
||||||
|
CALL vn.printer_checkSector(NEW.labelerFk, NEW.sectorFk);
|
||||||
|
|
||||||
|
INSERT IGNORE INTO vn.operator (workerFk)
|
||||||
|
VALUES (NEW.id);
|
||||||
|
|
||||||
|
UPDATE operator
|
||||||
|
SET labelerFk = NEW.labelerFk,
|
||||||
|
sectorFk = NEW.sectorFk
|
||||||
|
WHERE workerFk = NEW.id;
|
||||||
|
END IF;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
||||||
|
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost`
|
||||||
|
SQL SECURITY DEFINER
|
||||||
|
VIEW `vn`.`operatorWorkerCode`
|
||||||
|
AS SELECT `o`.`workerFk` AS `workerFk`,
|
||||||
|
concat(`w`.`firstName`, ' ', `w`.`lastName`) AS `fullName`,
|
||||||
|
`w`.`code` AS `code`,
|
||||||
|
`o`.`numberOfWagons` AS `numberOfWagons`
|
||||||
|
FROM (
|
||||||
|
(
|
||||||
|
`vn`.`worker` `w`
|
||||||
|
JOIN `vn`.`operator` `o` ON(`o`.`workerFk` = `w`.`id`)
|
||||||
|
)
|
||||||
|
JOIN `vn`.`sector` `s` ON(`o`.`sectorFk` = `s`.`id`)
|
||||||
|
)
|
||||||
|
WHERE `o`.`sectorFk` IS NOT NULL
|
||||||
|
AND `s`.`code` IN (
|
||||||
|
'H2',
|
||||||
|
'H2',
|
||||||
|
'PEQUES_H',
|
||||||
|
'ALTILLO COMP',
|
||||||
|
'ALTILLO ARTI'
|
||||||
|
)
|
|
@ -0,0 +1,47 @@
|
||||||
|
DROP PROCEDURE IF EXISTS `vn`.`ticket_getWarnings`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
$$
|
||||||
|
CREATE PROCEDURE `vn`.`ticket_getWarnings`()
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Calcula las adventencias para un conjunto de tickets.
|
||||||
|
* Agrupados por ticket
|
||||||
|
*
|
||||||
|
* @table tmp.sale_getWarnings(ticketFk) Identificadores de los tickets a calcular
|
||||||
|
* @return tmp.ticket_warnings
|
||||||
|
*/
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.sale_warnings;
|
||||||
|
CREATE TEMPORARY TABLE tmp.sale_warnings (
|
||||||
|
ticketFk INT(11),
|
||||||
|
saleFk INT(11),
|
||||||
|
isFragile INTEGER(1) DEFAULT 0,
|
||||||
|
PRIMARY KEY (ticketFk, saleFk)
|
||||||
|
) ENGINE = MEMORY;
|
||||||
|
|
||||||
|
-- Frágil
|
||||||
|
INSERT INTO tmp.sale_warnings(ticketFk, saleFk, isFragile)
|
||||||
|
SELECT tt.ticketFk, s.id, TRUE
|
||||||
|
FROM tmp.sale_getWarnings tt
|
||||||
|
LEFT JOIN sale s ON s.ticketFk = tt.ticketFk
|
||||||
|
LEFT JOIN item i ON i.id = s.itemFk
|
||||||
|
LEFT JOIN itemType it ON it.id = i.typeFk
|
||||||
|
LEFT JOIN agencyMode am ON am.id = tt.agencyModeFk
|
||||||
|
LEFT JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk
|
||||||
|
WHERE dm.code IN ('AGENCY')
|
||||||
|
AND it.isFragile;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_warnings;
|
||||||
|
CREATE TEMPORARY TABLE tmp.ticket_warnings
|
||||||
|
(PRIMARY KEY (ticketFk))
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT
|
||||||
|
sw.ticketFk,
|
||||||
|
MAX(sw.isFragile) AS isFragile
|
||||||
|
FROM tmp.sale_warnings sw
|
||||||
|
GROUP BY sw.ticketFk;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE
|
||||||
|
tmp.sale_warnings;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -164,7 +164,7 @@ INSERT INTO `vn`.`warehouse`(`id`, `name`, `code`, `isComparative`, `isInventory
|
||||||
(3, 'Warehouse Three', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1),
|
(3, 'Warehouse Three', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1),
|
||||||
(4, 'Warehouse Four', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1),
|
(4, 'Warehouse Four', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1),
|
||||||
(5, 'Warehouse Five', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1),
|
(5, 'Warehouse Five', NULL, 1, 1, 1, 1, 0, 0, 2, 1, 1),
|
||||||
(13, 'Inventory', NULL, 1, 1, 1, 0, 0, 0, 2, 1, 0),
|
(13, 'Inventory', 'inv', 1, 1, 1, 0, 0, 0, 2, 1, 0),
|
||||||
(60, 'Algemesi', NULL, 1, 1, 1, 0, 0, 0, 2, 1, 0);
|
(60, 'Algemesi', NULL, 1, 1, 1, 0, 0, 0, 2, 1, 0);
|
||||||
|
|
||||||
|
|
||||||
|
@ -173,10 +173,15 @@ INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPrepare
|
||||||
(1, 'First sector', 1, 1, 'FIRST'),
|
(1, 'First sector', 1, 1, 'FIRST'),
|
||||||
(2, 'Second sector', 2, 0, 'SECOND');
|
(2, 'Second sector', 2, 0, 'SECOND');
|
||||||
|
|
||||||
INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`)
|
INSERT INTO `vn`.`operator` (`workerFk`, `numberOfWagons`, `trainFk`, `itemPackingTypeFk`, `warehouseFk`, `sectorFk`, `labelerFk`)
|
||||||
|
VALUES ('1106', '1', '1', 'H', '1', '1', '1'),
|
||||||
|
('1107', '1', '1', 'V', '1', '2', '1');
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`, `ipAddress`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'printer1', 'path1', 0, 1),
|
(1, 'printer1', 'path1', 0, 1 , NULL),
|
||||||
(2, 'printer2', 'path2', 1, 1);
|
(2, 'printer2', 'path2', 1, 1 , NULL),
|
||||||
|
(4, 'printer4', 'path4', 0, NULL, '10.1.10.4');
|
||||||
|
|
||||||
INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `sectorFk`, `labelerFk`)
|
INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `sectorFk`, `labelerFk`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -294,7 +299,8 @@ INSERT INTO `vn`.`payMethod`(`id`,`code`, `name`, `graceDays`, `outstandingDebt
|
||||||
INSERT INTO `vn`.`payDem`(`id`, `payDem`)
|
INSERT INTO `vn`.`payDem`(`id`, `payDem`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 10),
|
(1, 10),
|
||||||
(2, 20);
|
(2, 20),
|
||||||
|
(7, 0);
|
||||||
|
|
||||||
INSERT INTO `vn`.`autonomy`(`id`, `name`, `countryFk`)
|
INSERT INTO `vn`.`autonomy`(`id`, `name`, `countryFk`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -495,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
|
||||||
|
@ -571,14 +578,13 @@ INSERT INTO `vn`.`taxArea` (`code`, `claveOperacionFactura`, `CodigoTransaccion`
|
||||||
('NATIONAL', 0, 1),
|
('NATIONAL', 0, 1),
|
||||||
('WORLD', 2, 15);
|
('WORLD', 2, 15);
|
||||||
|
|
||||||
INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaFk`, `isCEE`)
|
INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaFk`, `isCEE`, `type`)
|
||||||
VALUES
|
VALUES
|
||||||
('A', 'Global nacional', 1, 'NATIONAL', 0),
|
('A', 'Global nacional', 1, 'NATIONAL', 0, 'global'),
|
||||||
('T', 'Española rapida', 1, 'NATIONAL', 0),
|
('T', 'Española rapida', 1, 'NATIONAL', 0, 'quick'),
|
||||||
('V', 'Intracomunitaria global', 0, 'CEE', 1),
|
('V', 'Intracomunitaria global', 0, 'CEE', 1, 'global'),
|
||||||
('M', 'Múltiple nacional', 1, 'NATIONAL', 0),
|
('M', 'Múltiple nacional', 1, 'NATIONAL', 0, 'quick'),
|
||||||
('E', 'Exportación rápida', 0, 'WORLD', 0);
|
('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick');
|
||||||
;
|
|
||||||
|
|
||||||
INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`)
|
INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -733,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);
|
||||||
|
@ -833,14 +841,14 @@ INSERT INTO `vn`.`temperature`(`code`, `name`, `description`)
|
||||||
('warm', 'Warm', 'Warm'),
|
('warm', 'Warm', 'Warm'),
|
||||||
('cool', 'Cool', 'Cool');
|
('cool', 'Cool', 'Cool');
|
||||||
|
|
||||||
INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`, `workerFk`, `isPackaging`, `temperatureFk`)
|
INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`, `workerFk`, `isPackaging`, `temperatureFk`, `isFragile`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'CRI', 'Crisantemo', 2, 31, 35, 0, 'cool'),
|
(1, 'CRI', 'Crisantemo', 2, 31, 35, 0, 'cool', 0),
|
||||||
(2, 'ITG', 'Anthurium', 1, 31, 35, 0, 'cool'),
|
(2, 'ITG', 'Anthurium', 1, 31, 35, 0, 'cool', 1),
|
||||||
(3, 'WPN', 'Paniculata', 2, 31, 35, 0, 'cool'),
|
(3, 'WPN', 'Paniculata', 2, 31, 35, 0, 'cool', 0),
|
||||||
(4, 'PRT', 'Delivery ports', 3, NULL, 35, 1, 'warm'),
|
(4, 'PRT', 'Delivery ports', 3, NULL, 35, 1, 'warm', 0),
|
||||||
(5, 'CON', 'Container', 3, NULL, 35, 1, 'warm'),
|
(5, 'CON', 'Container', 3, NULL, 35, 1, 'warm', 0),
|
||||||
(6, 'ALS', 'Alstroemeria', 1, 31, 16, 0, 'warm');
|
(6, 'ALS', 'Alstroemeria', 1, 31, 16, 0, 'warm', 1);
|
||||||
|
|
||||||
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`)
|
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -2367,11 +2375,11 @@ INSERT INTO `vn`.`device` (`sn`, `model`, `userFk`)
|
||||||
VALUES
|
VALUES
|
||||||
('aaa', 'android', '9');
|
('aaa', 'android', '9');
|
||||||
|
|
||||||
INSERT INTO `vn`.`queuePriority`(`id`, `priority`)
|
INSERT INTO `vn`.`queuePriority`(`id`, `priority`, `code`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'Alta'),
|
(1, 'Alta', 'high'),
|
||||||
(2, 'Normal'),
|
(2, 'Normal', 'normal'),
|
||||||
(3, 'Baja');
|
(3, 'Baja', 'low');
|
||||||
|
|
||||||
INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`, `weekMaxBreak`, `weekMaxScope`, `askInOut`)
|
INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`, `weekMaxBreak`, `weekMaxScope`, `askInOut`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -2626,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`)
|
||||||
|
@ -2783,6 +2791,10 @@ INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
|
||||||
('lilium', 'dev', 'http://localhost:8080/#/'),
|
('lilium', 'dev', 'http://localhost:8080/#/'),
|
||||||
('salix', 'dev', 'http://localhost:5000/#!/');
|
('salix', 'dev', 'http://localhost:5000/#!/');
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`)
|
||||||
|
VALUES
|
||||||
|
(3, 'invoice', NULL, 'InvoiceOuts/{refFk}/invoice-out-pdf');
|
||||||
|
|
||||||
INSERT INTO `vn`.`payDemDetail` (`id`, `detail`)
|
INSERT INTO `vn`.`payDemDetail` (`id`, `detail`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1);
|
(1, 1);
|
||||||
|
@ -2821,4 +2833,11 @@ INSERT INTO `vn`.`deviceProductionUser` (`deviceProductionFk`, `userFk`, `create
|
||||||
(1, 1, util.VN_NOW()),
|
(1, 1, util.VN_NOW()),
|
||||||
(3, 3, util.VN_NOW());
|
(3, 3, util.VN_NOW());
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`workerTimeControlMail` (`id`, `workerFk`, `year`, `week`, `state`, `updated`, `sendedCounter`, `reason`)
|
||||||
|
VALUES
|
||||||
|
(1, 9, 2000, 49, 'REVISE', util.VN_NOW(), 1, 'test2'),
|
||||||
|
(2, 9, 2000, 50, 'SENDED', util.VN_NOW(), 1, NULL),
|
||||||
|
(3, 9, 2000, 51, 'CONFIRMED', util.VN_NOW(), 1, NULL),
|
||||||
|
(4, 9, 2001, 1, 'SENDED', util.VN_NOW(), 1, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19742,6 +19742,102 @@ DELIMITER ;
|
||||||
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
||||||
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
||||||
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||||
|
/*!50003 DROP FUNCTION IF EXISTS `CURDATE` */;
|
||||||
|
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||||
|
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||||
|
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
|
||||||
|
/*!50003 SET character_set_client = utf8mb4 */ ;
|
||||||
|
/*!50003 SET character_set_results = utf8mb4 */ ;
|
||||||
|
/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ;
|
||||||
|
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
|
||||||
|
/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ;
|
||||||
|
DELIMITER ;;
|
||||||
|
CREATE DEFINER=`root`@`localhost` FUNCTION `util`.`CURDATE`() RETURNS date
|
||||||
|
DETERMINISTIC
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* @return The mock date
|
||||||
|
**/
|
||||||
|
|
||||||
|
RETURN DATE(mockTime());
|
||||||
|
END ;;
|
||||||
|
DELIMITER ;
|
||||||
|
/*!50003 SET sql_mode = @saved_sql_mode */ ;
|
||||||
|
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
||||||
|
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
||||||
|
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||||
|
/*!50003 DROP FUNCTION IF EXISTS `mockTime` */;
|
||||||
|
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||||
|
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||||
|
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
|
||||||
|
/*!50003 SET character_set_client = utf8mb4 */ ;
|
||||||
|
/*!50003 SET character_set_results = utf8mb4 */ ;
|
||||||
|
/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ;
|
||||||
|
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
|
||||||
|
/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ;
|
||||||
|
DELIMITER ;;
|
||||||
|
CREATE DEFINER=`root`@`localhost` FUNCTION `util`.`mockTime`() RETURNS datetime
|
||||||
|
DETERMINISTIC
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Returns the mockTime with predefined timezone or current dateTime
|
||||||
|
* depending of config.mockEnabled
|
||||||
|
*
|
||||||
|
* @return formatted datetime
|
||||||
|
*/
|
||||||
|
DECLARE vMockEnabled BOOL;
|
||||||
|
|
||||||
|
SELECT mockEnabled INTO vMockEnabled FROM config LIMIT 1;
|
||||||
|
|
||||||
|
IF vMockEnabled THEN
|
||||||
|
RETURN mockTimeBase(FALSE);
|
||||||
|
ELSE
|
||||||
|
RETURN NOW();
|
||||||
|
END IF;
|
||||||
|
END ;;
|
||||||
|
DELIMITER ;
|
||||||
|
/*!50003 SET sql_mode = @saved_sql_mode */ ;
|
||||||
|
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
||||||
|
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
||||||
|
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||||
|
/*!50003 DROP FUNCTION IF EXISTS `mockTimeBase` */;
|
||||||
|
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||||
|
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||||
|
/*!50003 SET @saved_col_connection = @@collation_connection */ ;
|
||||||
|
/*!50003 SET character_set_client = utf8mb4 */ ;
|
||||||
|
/*!50003 SET character_set_results = utf8mb4 */ ;
|
||||||
|
/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ;
|
||||||
|
/*!50003 SET @saved_sql_mode = @@sql_mode */ ;
|
||||||
|
/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ;
|
||||||
|
DELIMITER ;;
|
||||||
|
CREATE DEFINER=`root`@`localhost` FUNCTION `util`.`mockTimeBase`(vIsUtc BOOL) RETURNS datetime
|
||||||
|
DETERMINISTIC
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Returns the date formatted to utc if vIsUtc or config.mocTz if not
|
||||||
|
*
|
||||||
|
* @param vIsUtc If date must be returned as UTC format
|
||||||
|
* @return The formatted mock time
|
||||||
|
*/
|
||||||
|
DECLARE vMockUtcTime DATETIME;
|
||||||
|
DECLARE vMockTz VARCHAR(255);
|
||||||
|
|
||||||
|
SELECT mockUtcTime, mockTz
|
||||||
|
INTO vMockUtcTime, vMockTz
|
||||||
|
FROM config
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
|
IF vIsUtc OR vMockTz IS NULL THEN
|
||||||
|
RETURN vMockUtcTime;
|
||||||
|
ELSE
|
||||||
|
RETURN CONVERT_TZ(vMockUtcTime, '+00:00', vMockTz);
|
||||||
|
END IF;
|
||||||
|
END ;;
|
||||||
|
DELIMITER ;
|
||||||
|
/*!50003 SET sql_mode = @saved_sql_mode */ ;
|
||||||
|
/*!50003 SET character_set_client = @saved_cs_client */ ;
|
||||||
|
/*!50003 SET character_set_results = @saved_cs_results */ ;
|
||||||
|
/*!50003 SET collation_connection = @saved_col_connection */ ;
|
||||||
/*!50003 DROP FUNCTION IF EXISTS `firstDayOfYear` */;
|
/*!50003 DROP FUNCTION IF EXISTS `firstDayOfYear` */;
|
||||||
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
/*!50003 SET @saved_cs_client = @@character_set_client */ ;
|
||||||
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
/*!50003 SET @saved_cs_results = @@character_set_results */ ;
|
||||||
|
@ -32632,7 +32728,7 @@ CREATE TABLE `printQueue` (
|
||||||
CONSTRAINT `printQueue_printerFk` FOREIGN KEY (`printerFk`) REFERENCES `printer` (`id`) ON UPDATE CASCADE,
|
CONSTRAINT `printQueue_printerFk` FOREIGN KEY (`printerFk`) REFERENCES `printer` (`id`) ON UPDATE CASCADE,
|
||||||
CONSTRAINT `printQueue_priorityFk` FOREIGN KEY (`priorityFk`) REFERENCES `queuePriority` (`id`) ON UPDATE CASCADE,
|
CONSTRAINT `printQueue_priorityFk` FOREIGN KEY (`priorityFk`) REFERENCES `queuePriority` (`id`) ON UPDATE CASCADE,
|
||||||
CONSTRAINT `printQueue_report` FOREIGN KEY (`reportFk`) REFERENCES `report` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
CONSTRAINT `printQueue_report` FOREIGN KEY (`reportFk`) REFERENCES `report` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
) ENGINE=InnoDBDEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
--
|
--
|
||||||
|
@ -68286,11 +68382,11 @@ BEGIN
|
||||||
FROM ticketConfig;
|
FROM ticketConfig;
|
||||||
|
|
||||||
IF vWarehouseInventory IS NULL THEN
|
IF vWarehouseInventory IS NULL THEN
|
||||||
CALL util.throw('Warehouse inventory not seted');
|
CALL util.throw('Warehouse inventory not set');
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
IF vComponentCost IS NULL THEN
|
IF vComponentCost IS NULL THEN
|
||||||
CALL util.throw('Component cost not seted');
|
CALL util.throw('Component cost not set');
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SET vDateEnd = vDated + INTERVAL 1 DAY;
|
SET vDateEnd = vDated + INTERVAL 1 DAY;
|
||||||
|
@ -81124,3 +81220,4 @@ USE `vn`;
|
||||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
|
||||||
-- Dump completed on 2023-02-21 8:14:30
|
-- Dump completed on 2023-02-21 8:14:30
|
||||||
|
|
||||||
|
|
|
@ -524,7 +524,6 @@ export default {
|
||||||
},
|
},
|
||||||
itemLog: {
|
itemLog: {
|
||||||
anyLineCreated: 'vn-item-log > vn-log vn-tbody > vn-tr',
|
anyLineCreated: 'vn-item-log > vn-log vn-tbody > vn-tr',
|
||||||
fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) table tr:nth-child(2) td.after',
|
|
||||||
},
|
},
|
||||||
ticketSummary: {
|
ticketSummary: {
|
||||||
header: 'vn-ticket-summary > vn-card > h5',
|
header: 'vn-ticket-summary > vn-card > h5',
|
||||||
|
@ -1040,7 +1039,6 @@ export default {
|
||||||
boss: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bossFk"]',
|
boss: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bossFk"]',
|
||||||
role: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.roleFk"]',
|
role: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.roleFk"]',
|
||||||
iban: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.iban"]',
|
iban: 'vn-worker-create vn-textfield[ng-model="$ctrl.worker.iban"]',
|
||||||
switft: 'vn-worker-create vn-autocomplete[ng-model="$ctrl.worker.bankEntityFk"]',
|
|
||||||
createButton: 'vn-worker-create vn-submit[label="Create"]',
|
createButton: 'vn-worker-create vn-submit[label="Create"]',
|
||||||
},
|
},
|
||||||
workerPda: {
|
workerPda: {
|
||||||
|
@ -1052,20 +1050,22 @@ export default {
|
||||||
invoiceOutIndex: {
|
invoiceOutIndex: {
|
||||||
topbarSearch: 'vn-searchbar',
|
topbarSearch: 'vn-searchbar',
|
||||||
searchResult: 'vn-invoice-out-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
searchResult: 'vn-invoice-out-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
||||||
createInvoice: 'vn-invoice-out-index > div > vn-vertical > vn-button > button vn-icon[icon="add"]',
|
createInvoice: 'vn-invoice-out-index > div > vn-button > button vn-icon[icon="add"]',
|
||||||
createManualInvoice: 'vn-item[name="manualInvoice"]',
|
|
||||||
createGlobalInvoice: 'vn-item[name="globalInvoice"]',
|
|
||||||
manualInvoiceForm: '.vn-invoice-out-manual',
|
manualInvoiceForm: '.vn-invoice-out-manual',
|
||||||
manualInvoiceTicket: 'vn-autocomplete[ng-model="$ctrl.invoice.ticketFk"]',
|
manualInvoiceTicket: 'vn-autocomplete[ng-model="$ctrl.invoice.ticketFk"]',
|
||||||
manualInvoiceClient: 'vn-autocomplete[ng-model="$ctrl.invoice.clientFk"]',
|
manualInvoiceClient: 'vn-autocomplete[ng-model="$ctrl.invoice.clientFk"]',
|
||||||
manualInvoiceSerial: 'vn-autocomplete[ng-model="$ctrl.invoice.serial"]',
|
manualInvoiceSerial: 'vn-autocomplete[ng-model="$ctrl.invoice.serial"]',
|
||||||
manualInvoiceTaxArea: 'vn-autocomplete[ng-model="$ctrl.invoice.taxArea"]',
|
manualInvoiceTaxArea: 'vn-autocomplete[ng-model="$ctrl.invoice.taxArea"]',
|
||||||
saveInvoice: 'button[response="accept"]',
|
saveInvoice: 'button[response="accept"]'
|
||||||
globalInvoiceForm: '.vn-invoice-out-global-invoicing',
|
},
|
||||||
globalInvoiceClientsRange: 'vn-radio[val="clientsRange"]',
|
invoiceOutGlobalInvoicing: {
|
||||||
globalInvoiceDate: '[ng-model="$ctrl.invoice.invoiceDate"]',
|
oneClient: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-vertical > vn-radio[val="one"]',
|
||||||
globalInvoiceFromClient: '[ng-model="$ctrl.invoice.fromClientId"]',
|
allClients: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-vertical > vn-radio[val="all"]',
|
||||||
globalInvoiceToClient: '[ng-model="$ctrl.invoice.toClientId"]',
|
clientId: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-autocomplete[ng-model="$ctrl.clientId"]',
|
||||||
|
printer: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-autocomplete[ng-model="$ctrl.printerFk"]',
|
||||||
|
makeInvoice: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-submit',
|
||||||
|
invoiceDate: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-date-picker[ng-model="$ctrl.invoiceDate"]',
|
||||||
|
maxShipped: 'vn-invoice-out-global-invoicing vn-side-menu form > vn-vertical > vn-date-picker[ng-model="$ctrl.maxShipped"]'
|
||||||
},
|
},
|
||||||
invoiceOutDescriptor: {
|
invoiceOutDescriptor: {
|
||||||
moreMenu: 'vn-invoice-out-descriptor vn-icon-button[icon=more_vert]',
|
moreMenu: 'vn-invoice-out-descriptor vn-icon-button[icon=more_vert]',
|
||||||
|
|
|
@ -27,7 +27,7 @@ describe('Worker time control path', () => {
|
||||||
date.setMonth(date.getMonth() + 1);
|
date.setMonth(date.getMonth() + 1);
|
||||||
let month = date.toLocaleString('default', {month: 'long'});
|
let month = date.toLocaleString('default', {month: 'long'});
|
||||||
|
|
||||||
await page.click(selectors.workerTimeControl.nextMonthButton);
|
await page.waitToClick(selectors.workerTimeControl.nextMonthButton);
|
||||||
let result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
let result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
||||||
|
|
||||||
expect(result).toContain(month);
|
expect(result).toContain(month);
|
||||||
|
@ -36,7 +36,7 @@ describe('Worker time control path', () => {
|
||||||
date.setDate(1);
|
date.setDate(1);
|
||||||
month = date.toLocaleString('default', {month: 'long'});
|
month = date.toLocaleString('default', {month: 'long'});
|
||||||
|
|
||||||
await page.click(selectors.workerTimeControl.previousMonthButton);
|
await page.waitToClick(selectors.workerTimeControl.previousMonthButton);
|
||||||
result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
||||||
|
|
||||||
expect(result).toContain(month);
|
expect(result).toContain(month);
|
||||||
|
@ -49,7 +49,7 @@ describe('Worker time control path', () => {
|
||||||
|
|
||||||
await page.loginAndModule('salesBoss', 'worker');
|
await page.loginAndModule('salesBoss', 'worker');
|
||||||
await page.goto(`http://localhost:5000/#!/worker/${hankPymId}/time-control?timestamp=${timestamp}`);
|
await page.goto(`http://localhost:5000/#!/worker/${hankPymId}/time-control?timestamp=${timestamp}`);
|
||||||
await page.click(selectors.workerTimeControl.secondWeekDay);
|
await page.waitToClick(selectors.workerTimeControl.secondWeekDay);
|
||||||
|
|
||||||
result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
result = await page.getProperty(selectors.workerTimeControl.monthName, 'innerText');
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ describe('Worker create path', () => {
|
||||||
await page.write(selectors.workerCreate.street, 'S/ Doomstadt');
|
await page.write(selectors.workerCreate.street, 'S/ Doomstadt');
|
||||||
await page.write(selectors.workerCreate.email, 'doctorDoom@marvel.com');
|
await page.write(selectors.workerCreate.email, 'doctorDoom@marvel.com');
|
||||||
await page.write(selectors.workerCreate.iban, 'ES9121000418450200051332');
|
await page.write(selectors.workerCreate.iban, 'ES9121000418450200051332');
|
||||||
await page.autocompleteSearch(selectors.workerCreate.switft, 'BBKKESMMMMM');
|
|
||||||
|
|
||||||
// should check for autocompleted worker code and worker user name
|
// should check for autocompleted worker code and worker user name
|
||||||
const workerCode = await page
|
const workerCode = await page
|
||||||
|
|
|
@ -48,17 +48,17 @@ describe('Item log path', () => {
|
||||||
await page.accessToSection('item.card.log');
|
await page.accessToSection('item.card.log');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should confirm the log is showing 5 entries`, async() => {
|
it(`should confirm the log is showing 4 entries`, async() => {
|
||||||
await page.waitForSelector(selectors.itemLog.anyLineCreated);
|
await page.waitForSelector(selectors.itemLog.anyLineCreated);
|
||||||
const anyLineCreatedCount = await page.countElement(selectors.itemLog.anyLineCreated);
|
const anyLineCreatedCount = await page.countElement(selectors.itemLog.anyLineCreated);
|
||||||
|
|
||||||
expect(anyLineCreatedCount).toEqual(5);
|
expect(anyLineCreatedCount).toEqual(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should confirm the log is showing the intrastat for the created item`, async() => {
|
xit(`should confirm the log is showing the intrastat for the created item`, async() => {
|
||||||
const fifthLineCreatedProperty = await page
|
const fifthLineCreatedProperty = await page
|
||||||
.waitToGetProperty(selectors.itemLog.fifthLineCreatedProperty, 'innerText');
|
.waitToGetProperty(selectors.itemLog.fifthLineCreatedProperty, 'innerText');
|
||||||
|
|
||||||
expect(fifthLineCreatedProperty).toEqual('Coral y materiales similares');
|
expect(fifthLineCreatedProperty).toEqual('05080000');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -197,6 +197,7 @@ describe('Ticket Edit sale path', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should check in the history that logs has been added', async() => {
|
it('should check in the history that logs has been added', async() => {
|
||||||
|
pending('https://redmine.verdnatura.es/issues/5455');
|
||||||
await page.reload({waitUntil: ['networkidle0', 'domcontentloaded']});
|
await page.reload({waitUntil: ['networkidle0', 'domcontentloaded']});
|
||||||
await page.waitToClick(selectors.ticketSales.firstSaleHistoryButton);
|
await page.waitToClick(selectors.ticketSales.firstSaleHistoryButton);
|
||||||
await page.waitForSelector(selectors.ticketSales.firstSaleHistory);
|
await page.waitForSelector(selectors.ticketSales.firstSaleHistory);
|
||||||
|
|
|
@ -9,7 +9,7 @@ describe('Ticket Create notes path', () => {
|
||||||
browser = await getBrowser();
|
browser = await getBrowser();
|
||||||
page = browser.page;
|
page = browser.page;
|
||||||
await page.loginAndModule('employee', 'ticket');
|
await page.loginAndModule('employee', 'ticket');
|
||||||
await page.accessToSearchResult('1');
|
await page.accessToSearchResult('5');
|
||||||
await page.accessToSection('ticket.card.observation');
|
await page.accessToSection('ticket.card.observation');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ describe('Ticket Future path', () => {
|
||||||
it('should search with the origin IPT', async() => {
|
it('should search with the origin IPT', async() => {
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
|
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketFuture.ipt, 'H');
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
|
|
||||||
expect(httpRequest).toContain('ipt=H');
|
expect(httpRequest).toContain('ipt=H');
|
||||||
|
@ -65,7 +65,7 @@ describe('Ticket Future path', () => {
|
||||||
|
|
||||||
await page.clearInput(selectors.ticketFuture.ipt);
|
await page.clearInput(selectors.ticketFuture.ipt);
|
||||||
|
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'H');
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
|
|
||||||
expect(httpRequest).toContain('futureIpt=H');
|
expect(httpRequest).toContain('futureIpt=H');
|
||||||
|
@ -108,7 +108,7 @@ describe('Ticket Future path', () => {
|
||||||
|
|
||||||
it('should search in smart-table with an IPT Destination', async() => {
|
it('should search in smart-table with an IPT Destination', async() => {
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'H');
|
||||||
|
|
||||||
expect(httpRequest).toContain('futureIpt');
|
expect(httpRequest).toContain('futureIpt');
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
||||||
|
|
|
@ -54,7 +54,7 @@ describe('Ticket Advance path', () => {
|
||||||
|
|
||||||
it('should search with the origin IPT', async() => {
|
it('should search with the origin IPT', async() => {
|
||||||
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'H');
|
||||||
await page.waitToClick(selectors.ticketAdvance.submit);
|
await page.waitToClick(selectors.ticketAdvance.submit);
|
||||||
|
|
||||||
expect(httpRequest).toContain('futureIpt=H');
|
expect(httpRequest).toContain('futureIpt=H');
|
||||||
|
@ -66,7 +66,7 @@ describe('Ticket Advance path', () => {
|
||||||
|
|
||||||
it('should search with the destination IPT', async() => {
|
it('should search with the destination IPT', async() => {
|
||||||
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'H');
|
||||||
await page.waitToClick(selectors.ticketAdvance.submit);
|
await page.waitToClick(selectors.ticketAdvance.submit);
|
||||||
|
|
||||||
expect(httpRequest).toContain('ipt=H');
|
expect(httpRequest).toContain('ipt=H');
|
||||||
|
@ -78,7 +78,7 @@ describe('Ticket Advance path', () => {
|
||||||
|
|
||||||
it('should search in smart-table with an IPT Origin', async() => {
|
it('should search in smart-table with an IPT Origin', async() => {
|
||||||
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'Vertical');
|
await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'V');
|
||||||
|
|
||||||
expect(httpRequest).toContain('futureIpt');
|
expect(httpRequest).toContain('futureIpt');
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ describe('Ticket Advance path', () => {
|
||||||
|
|
||||||
it('should search in smart-table with an IPT Destination', async() => {
|
it('should search in smart-table with an IPT Destination', async() => {
|
||||||
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'Vertical');
|
await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'V');
|
||||||
|
|
||||||
expect(httpRequest).toContain('ipt');
|
expect(httpRequest).toContain('ipt');
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ describe('InvoiceOut manual invoice path', () => {
|
||||||
|
|
||||||
it('should open the manual invoice form', async() => {
|
it('should open the manual invoice form', async() => {
|
||||||
await page.waitToClick(selectors.invoiceOutIndex.createInvoice);
|
await page.waitToClick(selectors.invoiceOutIndex.createInvoice);
|
||||||
await page.waitToClick(selectors.invoiceOutIndex.createManualInvoice);
|
|
||||||
await page.waitForSelector(selectors.invoiceOutIndex.manualInvoiceForm);
|
await page.waitForSelector(selectors.invoiceOutIndex.manualInvoiceForm);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -45,7 +44,6 @@ describe('InvoiceOut manual invoice path', () => {
|
||||||
|
|
||||||
it('should now open the manual invoice form', async() => {
|
it('should now open the manual invoice form', async() => {
|
||||||
await page.waitToClick(selectors.invoiceOutIndex.createInvoice);
|
await page.waitToClick(selectors.invoiceOutIndex.createInvoice);
|
||||||
await page.waitToClick(selectors.invoiceOutIndex.createManualInvoice);
|
|
||||||
await page.waitForSelector(selectors.invoiceOutIndex.manualInvoiceForm);
|
await page.waitForSelector(selectors.invoiceOutIndex.manualInvoiceForm);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -17,47 +17,27 @@ describe('InvoiceOut global invoice path', () => {
|
||||||
await browser.close();
|
await browser.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
let invoicesBefore;
|
let invoicesBeforeOneClient;
|
||||||
|
let invoicesBeforeAllClients;
|
||||||
|
let now = Date.vnNew();
|
||||||
|
|
||||||
it('should count the amount of invoices listed before globla invoces are made', async() => {
|
it('should count the amount of invoices listed before globla invoces are made', async() => {
|
||||||
invoicesBefore = await page.countElement(selectors.invoiceOutIndex.searchResult);
|
invoicesBeforeOneClient = await page.countElement(selectors.invoiceOutIndex.searchResult);
|
||||||
|
|
||||||
expect(invoicesBefore).toBeGreaterThanOrEqual(4);
|
expect(invoicesBeforeOneClient).toBeGreaterThanOrEqual(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should open the global invoice form', async() => {
|
it('should open the global invoice form', async() => {
|
||||||
await page.waitToClick(selectors.invoiceOutIndex.createInvoice);
|
await page.accessToSection('invoiceOut.global-invoicing');
|
||||||
await page.waitToClick(selectors.invoiceOutIndex.createGlobalInvoice);
|
|
||||||
await page.waitForSelector(selectors.invoiceOutIndex.globalInvoiceForm);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a global invoice for charles xavier today', async() => {
|
it('should create a global invoice for charles xavier today', async() => {
|
||||||
await page.pickDate(selectors.invoiceOutIndex.globalInvoiceDate);
|
await page.waitToClick(selectors.invoiceOutGlobalInvoicing.oneClient);
|
||||||
await page.waitToClick(selectors.invoiceOutIndex.globalInvoiceClientsRange);
|
await page.autocompleteSearch(selectors.invoiceOutGlobalInvoicing.clientId, '1108');
|
||||||
await page.autocompleteSearch(selectors.invoiceOutIndex.globalInvoiceFromClient, 'Petter Parker');
|
await page.pickDate(selectors.invoiceOutGlobalInvoicing.invoiceDate, now);
|
||||||
await page.autocompleteSearch(selectors.invoiceOutIndex.globalInvoiceToClient, 'Petter Parker');
|
await page.pickDate(selectors.invoiceOutGlobalInvoicing.maxShipped, now);
|
||||||
await page.waitToClick(selectors.invoiceOutIndex.saveInvoice);
|
await page.autocompleteSearch(selectors.invoiceOutGlobalInvoicing.printer, '1');
|
||||||
const message = await page.waitForSnackbar();
|
await page.waitToClick(selectors.invoiceOutGlobalInvoicing.makeInvoice);
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should count the amount of invoices listed after globla invocing', async() => {
|
|
||||||
await page.waitToClick('[icon="search"]');
|
|
||||||
await page.waitForTimeout(1000); // index search needs time to return results
|
|
||||||
const currentInvoices = await page.countElement(selectors.invoiceOutIndex.searchResult);
|
|
||||||
|
|
||||||
expect(currentInvoices).toBeGreaterThan(invoicesBefore);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create a global invoice for all clients today', async() => {
|
|
||||||
await page.waitToClick(selectors.invoiceOutIndex.createInvoice);
|
|
||||||
await page.waitToClick(selectors.invoiceOutIndex.createGlobalInvoice);
|
|
||||||
await page.waitForSelector(selectors.invoiceOutIndex.globalInvoiceForm);
|
|
||||||
await page.pickDate(selectors.invoiceOutIndex.globalInvoiceDate);
|
|
||||||
await page.waitToClick(selectors.invoiceOutIndex.saveInvoice);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -89,11 +89,13 @@ describe('Travel basic data path', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate to the travel logs', async() => {
|
it('should navigate to the travel logs', async() => {
|
||||||
|
pending('https://redmine.verdnatura.es/issues/5455');
|
||||||
await page.accessToSection('travel.card.log');
|
await page.accessToSection('travel.card.log');
|
||||||
await page.waitForState('travel.card.log');
|
await page.waitForState('travel.card.log');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should check the 1st log contains details from the changes made', async() => {
|
it('should check the 1st log contains details from the changes made', async() => {
|
||||||
|
pending('https://redmine.verdnatura.es/issues/5455');
|
||||||
const result = await page.waitToGetProperty(selectors.travelLog.firstLogFirstTD, 'innerText');
|
const result = await page.waitToGetProperty(selectors.travelLog.firstLogFirstTD, 'innerText');
|
||||||
|
|
||||||
expect(result).toContain('new reference!');
|
expect(result).toContain('new reference!');
|
||||||
|
|
|
@ -37,6 +37,6 @@ describe('Zone descriptor path', () => {
|
||||||
await page.accessToSection('ticket.card.log');
|
await page.accessToSection('ticket.card.log');
|
||||||
const lastChanges = await page.waitToGetProperty(selectors.ticketLog.changes, 'innerText');
|
const lastChanges = await page.waitToGetProperty(selectors.ticketLog.changes, 'innerText');
|
||||||
|
|
||||||
expect(lastChanges).toContain('Arreglar');
|
expect(lastChanges).toContain('1');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,9 +15,9 @@ export default class Calendar extends FormInput {
|
||||||
constructor($element, $scope, vnWeekDays, moment) {
|
constructor($element, $scope, vnWeekDays, moment) {
|
||||||
super($element, $scope);
|
super($element, $scope);
|
||||||
this.weekDays = vnWeekDays.locales;
|
this.weekDays = vnWeekDays.locales;
|
||||||
this.defaultDate = Date.vnNew();
|
|
||||||
this.displayControls = true;
|
this.displayControls = true;
|
||||||
this.moment = moment;
|
this.moment = moment;
|
||||||
|
this.defaultDate = Date.vnNew();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,12 +114,14 @@ export default class Calendar extends FormInput {
|
||||||
let day = date.getDate();
|
let day = date.getDate();
|
||||||
let wday = date.getDay();
|
let wday = date.getDay();
|
||||||
let month = date.getMonth();
|
let month = date.getMonth();
|
||||||
|
let year = date.getFullYear();
|
||||||
|
|
||||||
const currentDay = Date.vnNew().getDate();
|
const currentDay = Date.vnNew().getDate();
|
||||||
const currentMonth = Date.vnNew().getMonth();
|
const currentMonth = Date.vnNew().getMonth();
|
||||||
|
const currentYear = Date.vnNew().getFullYear();
|
||||||
|
|
||||||
let classes = {
|
let classes = {
|
||||||
today: day === currentDay && month === currentMonth,
|
today: day === currentDay && month === currentMonth && year === currentYear,
|
||||||
weekend: wday === 6 || wday === 0,
|
weekend: wday === 6 || wday === 0,
|
||||||
previous: month < this.month,
|
previous: month < this.month,
|
||||||
current: month == this.month,
|
current: month == this.month,
|
||||||
|
@ -207,9 +209,8 @@ export default class Calendar extends FormInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
repeatLast() {
|
repeatLast() {
|
||||||
if (!this.formatDay) return;
|
if (this.formatDay) {
|
||||||
|
const days = this.element.querySelectorAll('.days > .day');
|
||||||
let days = this.element.querySelectorAll('.days > .day');
|
|
||||||
for (let i = 0; i < days.length; i++) {
|
for (let i = 0; i < days.length; i++) {
|
||||||
this.formatDay({
|
this.formatDay({
|
||||||
$day: this.days[i],
|
$day: this.days[i],
|
||||||
|
@ -217,6 +218,16 @@ export default class Calendar extends FormInput {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.formatWeek) {
|
||||||
|
const weeks = this.element.querySelectorAll('.weeks > .day');
|
||||||
|
for (const week of weeks) {
|
||||||
|
this.formatWeek({
|
||||||
|
$element: week
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Calendar.$inject = ['$element', '$scope', 'vnWeekDays', 'moment'];
|
Calendar.$inject = ['$element', '$scope', 'vnWeekDays', 'moment'];
|
||||||
|
|
||||||
|
@ -228,6 +239,7 @@ ngModule.vnComponent('vnCalendar', {
|
||||||
hasEvents: '&?',
|
hasEvents: '&?',
|
||||||
getClass: '&?',
|
getClass: '&?',
|
||||||
formatDay: '&?',
|
formatDay: '&?',
|
||||||
|
formatWeek: '&?',
|
||||||
displayControls: '<?',
|
displayControls: '<?',
|
||||||
hideYear: '<?',
|
hideYear: '<?',
|
||||||
hideContiguous: '<?',
|
hideContiguous: '<?',
|
||||||
|
|
|
@ -25,8 +25,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/@uirouter/angularjs": {
|
"node_modules/@uirouter/angularjs": {
|
||||||
"version": "1.0.30",
|
"version": "1.0.30",
|
||||||
"resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.30.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-qkc3RFZc91S5K0gc/QVAXc9LGDPXjR04vDgG/11j8+yyZEuQojXxKxdLhKIepiPzqLmGRVqzBmBc27gtqaEeZg==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@uirouter/core": "6.0.8"
|
"@uirouter/core": "6.0.8"
|
||||||
},
|
},
|
||||||
|
@ -39,28 +38,22 @@
|
||||||
},
|
},
|
||||||
"node_modules/@uirouter/core": {
|
"node_modules/@uirouter/core": {
|
||||||
"version": "6.0.8",
|
"version": "6.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.8.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-Gc/BAW47i4L54p8dqYCJJZuv2s3tqlXQ0fvl6Zp2xrblELPVfxmjnc0eurx3XwfQdaqm3T6uls6tQKkof/4QMw==",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4.0.0"
|
"node": ">=4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/angular": {
|
"node_modules/angular": {
|
||||||
"version": "1.8.3",
|
"version": "1.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz",
|
"license": "MIT"
|
||||||
"integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw==",
|
|
||||||
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward."
|
|
||||||
},
|
},
|
||||||
"node_modules/angular-animate": {
|
"node_modules/angular-animate": {
|
||||||
"version": "1.8.2",
|
"version": "1.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz",
|
"license": "MIT"
|
||||||
"integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA==",
|
|
||||||
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward."
|
|
||||||
},
|
},
|
||||||
"node_modules/angular-moment": {
|
"node_modules/angular-moment": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.3.0.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-KG8rvO9MoaBLwtGnxTeUveSyNtrL+RNgGl1zqWN36+HDCCVGk2DGWOzqKWB6o+eTTbO3Opn4hupWKIElc8XETA==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"moment": ">=2.8.0 <3.0.0"
|
"moment": ">=2.8.0 <3.0.0"
|
||||||
},
|
},
|
||||||
|
@ -70,8 +63,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/angular-translate": {
|
"node_modules/angular-translate": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.0.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-Z/Fip5uUT2N85dPQ0sMEe1JdF5AehcDe4tg/9mWXNDVU531emHCg53ZND9Oe0dyNiGX5rWcJKmsL1Fujus1vGQ==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"angular": "^1.8.0"
|
"angular": "^1.8.0"
|
||||||
},
|
},
|
||||||
|
@ -81,29 +73,25 @@
|
||||||
},
|
},
|
||||||
"node_modules/angular-translate-loader-partial": {
|
"node_modules/angular-translate-loader-partial": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.19.0.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-NnMw13LMV4bPQmJK7/pZOZAnPxe0M5OtUHchADs5Gye7V7feonuEnrZ8e1CKhBlv9a7IQyWoqcBa4Lnhg8gk5w==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"angular-translate": "~2.19.0"
|
"angular-translate": "~2.19.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/argparse": {
|
"node_modules/argparse": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sprintf-js": "~1.0.2"
|
"sprintf-js": "~1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/croppie": {
|
"node_modules/croppie": {
|
||||||
"version": "2.6.5",
|
"version": "2.6.5",
|
||||||
"resolved": "https://registry.npmjs.org/croppie/-/croppie-2.6.5.tgz",
|
"license": "MIT"
|
||||||
"integrity": "sha512-IlChnVUGG5T3w2gRZIaQgBtlvyuYnlUWs2YZIXXR3H9KrlO1PtBT3j+ykxvy9eZIWhk+V5SpBmhCQz5UXKrEKQ=="
|
|
||||||
},
|
},
|
||||||
"node_modules/esprima": {
|
"node_modules/esprima": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
"license": "BSD-2-Clause",
|
||||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"esparse": "bin/esparse.js",
|
"esparse": "bin/esparse.js",
|
||||||
"esvalidate": "bin/esvalidate.js"
|
"esvalidate": "bin/esvalidate.js"
|
||||||
|
@ -114,8 +102,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "3.14.1",
|
"version": "3.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^1.0.7",
|
"argparse": "^1.0.7",
|
||||||
"esprima": "^4.0.0"
|
"esprima": "^4.0.0"
|
||||||
|
@ -126,42 +113,36 @@
|
||||||
},
|
},
|
||||||
"node_modules/mg-crud": {
|
"node_modules/mg-crud": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/mg-crud/-/mg-crud-1.1.2.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-mAR6t0aQHKnT0QHKHpLOi0kNPZfO36iMpIoiLjFHxuio6mIJyuveBJ4VNlNXJRxLh32/FLADEb41/sYo7QUKFw==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"angular": "^1.6.1"
|
"angular": "^1.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/moment": {
|
"node_modules/moment": {
|
||||||
"version": "2.29.4",
|
"version": "2.29.4",
|
||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/oclazyload": {
|
"node_modules/oclazyload": {
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz",
|
"license": "MIT"
|
||||||
"integrity": "sha512-HpOSYUgjtt6sTB/C6+FWsExR+9HCnXKsUA96RWkDXfv11C8Cc9X2DlR0WIZwFIiG6FQU0pwB5dhoYyut8bFAOQ=="
|
|
||||||
},
|
},
|
||||||
"node_modules/require-yaml": {
|
"node_modules/require-yaml": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
|
"license": "BSD",
|
||||||
"integrity": "sha512-M6eVEgLPRbeOhgSCnOTtdrOOEQzbXRchg24Xa13c39dMuraFKdI9emUo97Rih0YEFzSICmSKg8w4RQp+rd9pOQ==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-yaml": ""
|
"js-yaml": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/require-yaml/node_modules/argparse": {
|
"node_modules/require-yaml/node_modules/argparse": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
"license": "Python-2.0"
|
||||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
|
||||||
},
|
},
|
||||||
"node_modules/require-yaml/node_modules/js-yaml": {
|
"node_modules/require-yaml/node_modules/js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^2.0.1"
|
"argparse": "^2.0.1"
|
||||||
},
|
},
|
||||||
|
@ -171,13 +152,11 @@
|
||||||
},
|
},
|
||||||
"node_modules/sprintf-js": {
|
"node_modules/sprintf-js": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
"license": "BSD-3-Clause"
|
||||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
|
||||||
},
|
},
|
||||||
"node_modules/validator": {
|
"node_modules/validator": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/validator/-/validator-6.3.0.tgz",
|
"license": "MIT",
|
||||||
"integrity": "sha512-BylxTwhqwjQI5MDJF7amCy/L0ejJO+74DvCsLV52Lq3+3bhVcVMKqNqOiNcQJm2G48u9EAcw4xFERAmFbwXM9Q==",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
|
@ -186,73 +165,51 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@uirouter/angularjs": {
|
"@uirouter/angularjs": {
|
||||||
"version": "1.0.30",
|
"version": "1.0.30",
|
||||||
"resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.30.tgz",
|
|
||||||
"integrity": "sha512-qkc3RFZc91S5K0gc/QVAXc9LGDPXjR04vDgG/11j8+yyZEuQojXxKxdLhKIepiPzqLmGRVqzBmBc27gtqaEeZg==",
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@uirouter/core": "6.0.8"
|
"@uirouter/core": "6.0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@uirouter/core": {
|
"@uirouter/core": {
|
||||||
"version": "6.0.8",
|
"version": "6.0.8"
|
||||||
"resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.8.tgz",
|
|
||||||
"integrity": "sha512-Gc/BAW47i4L54p8dqYCJJZuv2s3tqlXQ0fvl6Zp2xrblELPVfxmjnc0eurx3XwfQdaqm3T6uls6tQKkof/4QMw=="
|
|
||||||
},
|
},
|
||||||
"angular": {
|
"angular": {
|
||||||
"version": "1.8.3",
|
"version": "1.8.3"
|
||||||
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz",
|
|
||||||
"integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw=="
|
|
||||||
},
|
},
|
||||||
"angular-animate": {
|
"angular-animate": {
|
||||||
"version": "1.8.2",
|
"version": "1.8.2"
|
||||||
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz",
|
|
||||||
"integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA=="
|
|
||||||
},
|
},
|
||||||
"angular-moment": {
|
"angular-moment": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.3.0.tgz",
|
|
||||||
"integrity": "sha512-KG8rvO9MoaBLwtGnxTeUveSyNtrL+RNgGl1zqWN36+HDCCVGk2DGWOzqKWB6o+eTTbO3Opn4hupWKIElc8XETA==",
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"moment": ">=2.8.0 <3.0.0"
|
"moment": ">=2.8.0 <3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"angular-translate": {
|
"angular-translate": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.0.tgz",
|
|
||||||
"integrity": "sha512-Z/Fip5uUT2N85dPQ0sMEe1JdF5AehcDe4tg/9mWXNDVU531emHCg53ZND9Oe0dyNiGX5rWcJKmsL1Fujus1vGQ==",
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"angular": "^1.8.0"
|
"angular": "^1.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"angular-translate-loader-partial": {
|
"angular-translate-loader-partial": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.19.0.tgz",
|
|
||||||
"integrity": "sha512-NnMw13LMV4bPQmJK7/pZOZAnPxe0M5OtUHchADs5Gye7V7feonuEnrZ8e1CKhBlv9a7IQyWoqcBa4Lnhg8gk5w==",
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"angular-translate": "~2.19.0"
|
"angular-translate": "~2.19.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"argparse": {
|
"argparse": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
|
||||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"sprintf-js": "~1.0.2"
|
"sprintf-js": "~1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"croppie": {
|
"croppie": {
|
||||||
"version": "2.6.5",
|
"version": "2.6.5"
|
||||||
"resolved": "https://registry.npmjs.org/croppie/-/croppie-2.6.5.tgz",
|
|
||||||
"integrity": "sha512-IlChnVUGG5T3w2gRZIaQgBtlvyuYnlUWs2YZIXXR3H9KrlO1PtBT3j+ykxvy9eZIWhk+V5SpBmhCQz5UXKrEKQ=="
|
|
||||||
},
|
},
|
||||||
"esprima": {
|
"esprima": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1"
|
||||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
|
||||||
},
|
},
|
||||||
"js-yaml": {
|
"js-yaml": {
|
||||||
"version": "3.14.1",
|
"version": "3.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
|
||||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"argparse": "^1.0.7",
|
"argparse": "^1.0.7",
|
||||||
"esprima": "^4.0.0"
|
"esprima": "^4.0.0"
|
||||||
|
@ -260,39 +217,27 @@
|
||||||
},
|
},
|
||||||
"mg-crud": {
|
"mg-crud": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/mg-crud/-/mg-crud-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-mAR6t0aQHKnT0QHKHpLOi0kNPZfO36iMpIoiLjFHxuio6mIJyuveBJ4VNlNXJRxLh32/FLADEb41/sYo7QUKFw==",
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"angular": "^1.6.1"
|
"angular": "^1.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"moment": {
|
"moment": {
|
||||||
"version": "2.29.4",
|
"version": "2.29.4"
|
||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
|
||||||
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
|
|
||||||
},
|
},
|
||||||
"oclazyload": {
|
"oclazyload": {
|
||||||
"version": "0.6.3",
|
"version": "0.6.3"
|
||||||
"resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz",
|
|
||||||
"integrity": "sha512-HpOSYUgjtt6sTB/C6+FWsExR+9HCnXKsUA96RWkDXfv11C8Cc9X2DlR0WIZwFIiG6FQU0pwB5dhoYyut8bFAOQ=="
|
|
||||||
},
|
},
|
||||||
"require-yaml": {
|
"require-yaml": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
|
|
||||||
"integrity": "sha512-M6eVEgLPRbeOhgSCnOTtdrOOEQzbXRchg24Xa13c39dMuraFKdI9emUo97Rih0YEFzSICmSKg8w4RQp+rd9pOQ==",
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"js-yaml": ""
|
"js-yaml": ""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": {
|
"argparse": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1"
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
|
||||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
|
||||||
},
|
},
|
||||||
"js-yaml": {
|
"js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"argparse": "^2.0.1"
|
"argparse": "^2.0.1"
|
||||||
}
|
}
|
||||||
|
@ -300,14 +245,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sprintf-js": {
|
"sprintf-js": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3"
|
||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
|
||||||
},
|
},
|
||||||
"validator": {
|
"validator": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.0"
|
||||||
"resolved": "https://registry.npmjs.org/validator/-/validator-6.3.0.tgz",
|
|
||||||
"integrity": "sha512-BylxTwhqwjQI5MDJF7amCy/L0ejJO+74DvCsLV52Lq3+3bhVcVMKqNqOiNcQJm2G48u9EAcw4xFERAmFbwXM9Q=="
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
const {Report, Email} = require('vn-print');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.printReport = async function(ctx, id, reportName) {
|
||||||
|
const args = Object.assign({}, ctx.args);
|
||||||
|
const params = {lang: ctx.req.getLocale()};
|
||||||
|
|
||||||
|
delete args.ctx;
|
||||||
|
for (const param in args)
|
||||||
|
params[param] = args[param];
|
||||||
|
|
||||||
|
const report = new Report(reportName, params);
|
||||||
|
const stream = await report.toPdfStream();
|
||||||
|
|
||||||
|
let fileName = `${reportName}`;
|
||||||
|
if (id) fileName += `-${id}`;
|
||||||
|
|
||||||
|
return [stream, 'application/pdf', `filename="${fileName}.pdf"`];
|
||||||
|
};
|
||||||
|
|
||||||
|
Self.printEmail = async function(ctx, id, templateName) {
|
||||||
|
const {accessToken} = ctx.req;
|
||||||
|
const args = Object.assign({}, ctx.args);
|
||||||
|
const params = {lang: ctx.req.getLocale()};
|
||||||
|
|
||||||
|
delete args.ctx;
|
||||||
|
for (const param in args)
|
||||||
|
params[param] = args[param];
|
||||||
|
|
||||||
|
params.isPreview = true;
|
||||||
|
params.access_token = accessToken.id;
|
||||||
|
|
||||||
|
const report = new Email(templateName, params);
|
||||||
|
const html = await report.render();
|
||||||
|
|
||||||
|
let fileName = `${templateName}`;
|
||||||
|
if (id) fileName += `-${id}`;
|
||||||
|
|
||||||
|
return [html, 'text/html', `filename=${fileName}.pdf"`];
|
||||||
|
};
|
||||||
|
|
||||||
|
Self.sendTemplate = async function(ctx, templateName) {
|
||||||
|
const args = Object.assign({}, ctx.args);
|
||||||
|
const params = {
|
||||||
|
recipient: args.recipient,
|
||||||
|
lang: ctx.req.getLocale()
|
||||||
|
};
|
||||||
|
|
||||||
|
delete args.ctx;
|
||||||
|
for (const param in args)
|
||||||
|
params[param] = args[param];
|
||||||
|
|
||||||
|
const email = new Email(templateName, params);
|
||||||
|
|
||||||
|
return email.send();
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,4 +1,3 @@
|
||||||
const pick = require('object.pick');
|
|
||||||
const LoopBackContext = require('loopback-context');
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
module.exports = function(Self) {
|
module.exports = function(Self) {
|
||||||
|
@ -6,344 +5,11 @@ module.exports = function(Self) {
|
||||||
Self.super_.setup.call(this);
|
Self.super_.setup.call(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
Self.observe('after save', async function(ctx) {
|
|
||||||
const loopBackContext = LoopBackContext.getCurrentContext();
|
|
||||||
await logInModel(ctx, loopBackContext);
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.observe('before save', async function(ctx) {
|
Self.observe('before save', async function(ctx) {
|
||||||
const appModels = ctx.Model.app.models;
|
ctx.options.httpCtx = LoopBackContext.getCurrentContext();
|
||||||
const definition = ctx.Model.definition;
|
|
||||||
const options = {};
|
|
||||||
|
|
||||||
// Check for transactions
|
|
||||||
if (ctx.options && ctx.options.transaction)
|
|
||||||
options.transaction = ctx.options.transaction;
|
|
||||||
|
|
||||||
let oldInstance;
|
|
||||||
let newInstance;
|
|
||||||
|
|
||||||
if (ctx.data) {
|
|
||||||
const changes = pick(ctx.currentInstance, Object.keys(ctx.data));
|
|
||||||
newInstance = ctx.data;
|
|
||||||
oldInstance = changes;
|
|
||||||
|
|
||||||
if (ctx.where && !ctx.currentInstance) {
|
|
||||||
const fields = Object.keys(ctx.data);
|
|
||||||
const modelName = definition.name;
|
|
||||||
|
|
||||||
ctx.oldInstances = await appModels[modelName].find({
|
|
||||||
where: ctx.where,
|
|
||||||
fields: fields
|
|
||||||
}, options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get changes from created instance
|
|
||||||
if (ctx.isNewInstance)
|
|
||||||
newInstance = ctx.instance.__data;
|
|
||||||
|
|
||||||
ctx.hookState.oldInstance = oldInstance;
|
|
||||||
ctx.hookState.newInstance = newInstance;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.observe('before delete', async function(ctx) {
|
Self.observe('before delete', async function(ctx) {
|
||||||
const appModels = ctx.Model.app.models;
|
ctx.options.httpCtx = LoopBackContext.getCurrentContext();
|
||||||
const definition = ctx.Model.definition;
|
|
||||||
const relations = ctx.Model.relations;
|
|
||||||
|
|
||||||
let options = {};
|
|
||||||
if (ctx.options && ctx.options.transaction)
|
|
||||||
options.transaction = ctx.options.transaction;
|
|
||||||
|
|
||||||
if (ctx.where) {
|
|
||||||
let affectedModel = definition.name;
|
|
||||||
let deletedInstances = await appModels[affectedModel].find({
|
|
||||||
where: ctx.where
|
|
||||||
}, options);
|
|
||||||
|
|
||||||
let relation = definition.settings.log.relation;
|
|
||||||
|
|
||||||
if (relation) {
|
|
||||||
let primaryKey = relations[relation].keyFrom;
|
|
||||||
|
|
||||||
let arrangedDeletedInstances = [];
|
|
||||||
for (let i = 0; i < deletedInstances.length; i++) {
|
|
||||||
if (primaryKey)
|
|
||||||
deletedInstances[i].originFk = deletedInstances[i][primaryKey];
|
|
||||||
let arrangedInstance = await fkToValue(deletedInstances[i], ctx);
|
|
||||||
arrangedDeletedInstances[i] = arrangedInstance;
|
|
||||||
}
|
|
||||||
ctx.hookState.oldInstance = arrangedDeletedInstances;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.observe('after delete', async function(ctx) {
|
|
||||||
const loopBackContext = LoopBackContext.getCurrentContext();
|
|
||||||
if (ctx.hookState.oldInstance)
|
|
||||||
logDeletedInstances(ctx, loopBackContext);
|
|
||||||
});
|
|
||||||
|
|
||||||
async function logDeletedInstances(ctx, loopBackContext) {
|
|
||||||
const appModels = ctx.Model.app.models;
|
|
||||||
const definition = ctx.Model.definition;
|
|
||||||
let options = {};
|
|
||||||
if (ctx.options && ctx.options.transaction)
|
|
||||||
options.transaction = ctx.options.transaction;
|
|
||||||
|
|
||||||
ctx.hookState.oldInstance.forEach(async instance => {
|
|
||||||
let userFk;
|
|
||||||
if (loopBackContext)
|
|
||||||
userFk = loopBackContext.active.accessToken.userId;
|
|
||||||
|
|
||||||
let changedModelValue = definition.settings.log.changedModelValue;
|
|
||||||
let logRecord = {
|
|
||||||
originFk: instance.originFk,
|
|
||||||
userFk: userFk,
|
|
||||||
action: 'delete',
|
|
||||||
changedModel: definition.name,
|
|
||||||
changedModelId: instance.id,
|
|
||||||
changedModelValue: instance[changedModelValue],
|
|
||||||
oldInstance: instance,
|
|
||||||
newInstance: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
delete instance.originFk;
|
|
||||||
|
|
||||||
let logModel = definition.settings.log.model;
|
|
||||||
await appModels[logModel].create(logRecord, options);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get log values from a foreign key
|
|
||||||
async function fkToValue(instance, ctx) {
|
|
||||||
const appModels = ctx.Model.app.models;
|
|
||||||
const relations = ctx.Model.relations;
|
|
||||||
let options = {};
|
|
||||||
|
|
||||||
// Check for transactions
|
|
||||||
if (ctx.options && ctx.options.transaction)
|
|
||||||
options.transaction = ctx.options.transaction;
|
|
||||||
|
|
||||||
const instanceCopy = JSON.parse(JSON.stringify(instance));
|
|
||||||
const result = {};
|
|
||||||
for (const key in instanceCopy) {
|
|
||||||
let value = instanceCopy[key];
|
|
||||||
|
|
||||||
if (value instanceof Object)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (value === undefined) continue;
|
|
||||||
|
|
||||||
if (value) {
|
|
||||||
for (let relationName in relations) {
|
|
||||||
const relation = relations[relationName];
|
|
||||||
if (relation.keyFrom == key && key != 'id') {
|
|
||||||
const model = relation.modelTo;
|
|
||||||
const modelName = relation.modelTo.modelName;
|
|
||||||
const properties = model && model.definition.properties;
|
|
||||||
const settings = model && model.definition.settings;
|
|
||||||
|
|
||||||
const recordSet = await appModels[modelName].findById(value, null, options);
|
|
||||||
|
|
||||||
const hasShowField = settings.log && settings.log.showField;
|
|
||||||
let showField = hasShowField && recordSet
|
|
||||||
&& recordSet[settings.log.showField];
|
|
||||||
|
|
||||||
if (!showField) {
|
|
||||||
const showFieldNames = [
|
|
||||||
'name',
|
|
||||||
'description',
|
|
||||||
'code',
|
|
||||||
'nickname'
|
|
||||||
];
|
|
||||||
for (field of showFieldNames) {
|
|
||||||
const propField = properties && properties[field];
|
|
||||||
const recordField = recordSet && recordSet[field];
|
|
||||||
|
|
||||||
if (propField && recordField) {
|
|
||||||
showField = field;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showField && recordSet && recordSet[showField]) {
|
|
||||||
value = recordSet[showField];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = recordSet && recordSet.id || value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result[key] = value;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function logInModel(ctx, loopBackContext) {
|
|
||||||
const appModels = ctx.Model.app.models;
|
|
||||||
const definition = ctx.Model.definition;
|
|
||||||
const defSettings = ctx.Model.definition.settings;
|
|
||||||
const relations = ctx.Model.relations;
|
|
||||||
|
|
||||||
const options = {};
|
|
||||||
if (ctx.options && ctx.options.transaction)
|
|
||||||
options.transaction = ctx.options.transaction;
|
|
||||||
|
|
||||||
let primaryKey;
|
|
||||||
for (let property in definition.properties) {
|
|
||||||
if (definition.properties[property].id) {
|
|
||||||
primaryKey = property;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!primaryKey) throw new Error('Primary key not found');
|
|
||||||
let originId;
|
|
||||||
|
|
||||||
// RELATIONS LOG
|
|
||||||
let changedModelId;
|
|
||||||
|
|
||||||
if (ctx.instance && !defSettings.log.relation) {
|
|
||||||
originId = ctx.instance.id;
|
|
||||||
changedModelId = ctx.instance.id;
|
|
||||||
} else if (defSettings.log.relation) {
|
|
||||||
primaryKey = relations[defSettings.log.relation].keyFrom;
|
|
||||||
|
|
||||||
if (ctx.where && ctx.where[primaryKey])
|
|
||||||
originId = ctx.where[primaryKey];
|
|
||||||
else if (ctx.instance) {
|
|
||||||
originId = ctx.instance[primaryKey];
|
|
||||||
changedModelId = ctx.instance.id;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
originId = ctx.currentInstance.id;
|
|
||||||
changedModelId = ctx.currentInstance.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the changedModelValue to save and the instances changed in case its an updateAll
|
|
||||||
let showField = defSettings.log.showField;
|
|
||||||
let where;
|
|
||||||
if (showField && (!ctx.instance || !ctx.instance[showField]) && ctx.where) {
|
|
||||||
changedModelId = [];
|
|
||||||
where = [];
|
|
||||||
let changedInstances = await appModels[definition.name].find({
|
|
||||||
where: ctx.where,
|
|
||||||
fields: ['id', showField, primaryKey]
|
|
||||||
}, options);
|
|
||||||
|
|
||||||
changedInstances.forEach(element => {
|
|
||||||
where.push(element[showField]);
|
|
||||||
changedModelId.push(element.id);
|
|
||||||
originId = element[primaryKey];
|
|
||||||
});
|
|
||||||
} else if (ctx.hookState.oldInstance)
|
|
||||||
where = ctx.instance[showField];
|
|
||||||
|
|
||||||
// Set oldInstance, newInstance, userFk and action
|
|
||||||
let oldInstance = {};
|
|
||||||
if (ctx.hookState.oldInstance)
|
|
||||||
Object.assign(oldInstance, ctx.hookState.oldInstance);
|
|
||||||
|
|
||||||
let newInstance = {};
|
|
||||||
if (ctx.hookState.newInstance)
|
|
||||||
Object.assign(newInstance, ctx.hookState.newInstance);
|
|
||||||
let userFk;
|
|
||||||
if (loopBackContext)
|
|
||||||
userFk = loopBackContext.active.accessToken.userId;
|
|
||||||
|
|
||||||
let action = setActionType(ctx);
|
|
||||||
|
|
||||||
removeUnloggable(definition, oldInstance);
|
|
||||||
removeUnloggable(definition, newInstance);
|
|
||||||
|
|
||||||
oldInstance = await fkToValue(oldInstance, ctx);
|
|
||||||
newInstance = await fkToValue(newInstance, ctx);
|
|
||||||
|
|
||||||
// Prevent log with no new changes
|
|
||||||
const hasNewChanges = Object.keys(newInstance).length;
|
|
||||||
if (!hasNewChanges) return;
|
|
||||||
|
|
||||||
let logRecord = {
|
|
||||||
originFk: originId,
|
|
||||||
userFk: userFk,
|
|
||||||
action: action,
|
|
||||||
changedModel: definition.name,
|
|
||||||
changedModelId: changedModelId, // Model property with an different data type will throw a NaN error
|
|
||||||
changedModelValue: where,
|
|
||||||
oldInstance: oldInstance,
|
|
||||||
newInstance: newInstance
|
|
||||||
};
|
|
||||||
|
|
||||||
let logsToSave = setLogsToSave(where, changedModelId, logRecord, ctx);
|
|
||||||
let logModel = defSettings.log.model;
|
|
||||||
|
|
||||||
await appModels[logModel].create(logsToSave, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes unwanted properties
|
|
||||||
* @param {*} definition Model definition
|
|
||||||
* @param {*} properties Modified object properties
|
|
||||||
*/
|
|
||||||
function removeUnloggable(definition, properties) {
|
|
||||||
const objectCopy = Object.assign({}, properties);
|
|
||||||
const propList = Object.keys(objectCopy);
|
|
||||||
const propDefs = new Map();
|
|
||||||
|
|
||||||
for (let property in definition.properties) {
|
|
||||||
const propertyDef = definition.properties[property];
|
|
||||||
|
|
||||||
propDefs.set(property, propertyDef);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let property of propList) {
|
|
||||||
const propertyDef = propDefs.get(property);
|
|
||||||
const firstChar = property.substring(0, 1);
|
|
||||||
const isPrivate = firstChar == '$';
|
|
||||||
|
|
||||||
if (isPrivate || !propertyDef)
|
|
||||||
delete properties[property];
|
|
||||||
|
|
||||||
if (!propertyDef) continue;
|
|
||||||
|
|
||||||
if (propertyDef.log === false || isPrivate)
|
|
||||||
delete properties[property];
|
|
||||||
else if (propertyDef.logValue === false)
|
|
||||||
properties[property] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this function retuns all the instances changed in case this is an updateAll
|
|
||||||
function setLogsToSave(changedInstances, changedInstancesIds, logRecord, ctx) {
|
|
||||||
let promises = [];
|
|
||||||
if (changedInstances && typeof changedInstances == 'object') {
|
|
||||||
for (let i = 0; i < changedInstances.length; i++) {
|
|
||||||
logRecord.changedModelId = changedInstancesIds[i];
|
|
||||||
logRecord.changedModelValue = changedInstances[i];
|
|
||||||
if (ctx.oldInstances)
|
|
||||||
logRecord.oldInstance = ctx.oldInstances[i];
|
|
||||||
promises.push(JSON.parse(JSON.stringify(logRecord)));
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
return logRecord;
|
|
||||||
|
|
||||||
return promises;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setActionType(ctx) {
|
|
||||||
let oldInstance = ctx.hookState.oldInstance;
|
|
||||||
let newInstance = ctx.hookState.newInstance;
|
|
||||||
|
|
||||||
if (oldInstance && newInstance)
|
|
||||||
return 'update';
|
|
||||||
else if (!oldInstance && newInstance)
|
|
||||||
return 'insert';
|
|
||||||
|
|
||||||
return 'delete';
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@ module.exports = function(Self) {
|
||||||
|
|
||||||
require('../methods/vn-model/getSetValues')(Self);
|
require('../methods/vn-model/getSetValues')(Self);
|
||||||
require('../methods/vn-model/getEnumValues')(Self);
|
require('../methods/vn-model/getEnumValues')(Self);
|
||||||
|
require('../methods/vn-model/printService')(Self);
|
||||||
|
|
||||||
Object.assign(Self, {
|
Object.assign(Self, {
|
||||||
setup() {
|
setup() {
|
||||||
|
|
|
@ -152,5 +152,7 @@
|
||||||
"It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo",
|
"It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo",
|
||||||
"It is not possible to modify cloned sales": "It is not possible to modify cloned sales",
|
"It is not possible to modify cloned sales": "It is not possible to modify cloned sales",
|
||||||
"Valid priorities: 1,2,3": "Valid priorities: 1,2,3",
|
"Valid priorities: 1,2,3": "Valid priorities: 1,2,3",
|
||||||
|
"Warehouse inventory not set": "Almacén inventario no está establecido",
|
||||||
|
"Component cost not set": "Componente coste no está estabecido",
|
||||||
"Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2"
|
"Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2"
|
||||||
}
|
}
|
|
@ -251,6 +251,7 @@
|
||||||
"Receipt's bank was not found": "No se encontró el banco del recibo",
|
"Receipt's bank was not found": "No se encontró el banco del recibo",
|
||||||
"This receipt was not compensated": "Este recibo no ha sido compensado",
|
"This receipt was not compensated": "Este recibo no ha sido compensado",
|
||||||
"Client's email was not found": "No se encontró el email del cliente",
|
"Client's email was not found": "No se encontró el email del cliente",
|
||||||
|
"Negative basis": "Base negativa",
|
||||||
"This worker code already exists": "Este codigo de trabajador ya existe",
|
"This worker code already exists": "Este codigo de trabajador ya existe",
|
||||||
"This personal mail already exists": "Este correo personal ya existe",
|
"This personal mail already exists": "Este correo personal ya existe",
|
||||||
"This worker already exists": "Este trabajador ya existe",
|
"This worker already exists": "Este trabajador ya existe",
|
||||||
|
@ -264,7 +265,11 @@
|
||||||
"It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas",
|
"It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas",
|
||||||
"A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.",
|
"A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.",
|
||||||
"There is no assigned email for this client": "No hay correo asignado para este cliente",
|
"There is no assigned email for this client": "No hay correo asignado para este cliente",
|
||||||
|
"Exists an invoice with a previous date": "Existe una factura con fecha anterior",
|
||||||
|
"Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite",
|
||||||
|
"Warehouse inventory not set": "El almacén inventario no está establecido",
|
||||||
"This locker has already been assigned": "Esta taquilla ya ha sido asignada",
|
"This locker has already been assigned": "Esta taquilla ya ha sido asignada",
|
||||||
"Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº {{id}}",
|
"Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº {{id}}",
|
||||||
"Not exist this branch": "La rama no existe"
|
"Not exist this branch": "La rama no existe",
|
||||||
|
"This ticket cannot be signed because it has not been boxed": "Este ticket no puede firmarse porque no ha sido encajado"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,41 @@ const mysql = require('mysql');
|
||||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
const MySQL = require('loopback-connector-mysql').MySQL;
|
const MySQL = require('loopback-connector-mysql').MySQL;
|
||||||
const EnumFactory = require('loopback-connector-mysql').EnumFactory;
|
const EnumFactory = require('loopback-connector-mysql').EnumFactory;
|
||||||
|
const Transaction = require('loopback-connector').Transaction;
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const limitSet = new Set([
|
||||||
|
'save',
|
||||||
|
'updateOrCreate',
|
||||||
|
'replaceOrCreate',
|
||||||
|
'replaceById',
|
||||||
|
'update'
|
||||||
|
]);
|
||||||
|
|
||||||
|
const opOpts = {
|
||||||
|
update: [
|
||||||
|
'update',
|
||||||
|
'replaceById',
|
||||||
|
// |insert
|
||||||
|
'save',
|
||||||
|
'updateOrCreate',
|
||||||
|
'replaceOrCreate'
|
||||||
|
],
|
||||||
|
delete: [
|
||||||
|
'destroy',
|
||||||
|
'destroyAll'
|
||||||
|
],
|
||||||
|
insert: [
|
||||||
|
'create'
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const opMap = new Map();
|
||||||
|
for (const op in opOpts) {
|
||||||
|
for (const met of opOpts[op])
|
||||||
|
opMap.set(met, op);
|
||||||
|
}
|
||||||
|
|
||||||
class VnMySQL extends MySQL {
|
class VnMySQL extends MySQL {
|
||||||
/**
|
/**
|
||||||
* Promisified version of execute().
|
* Promisified version of execute().
|
||||||
|
@ -219,6 +252,277 @@ class VnMySQL extends MySQL {
|
||||||
this.makePagination(filter)
|
this.makePagination(filter)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
create(model, data, opts, cb) {
|
||||||
|
const ctx = {data};
|
||||||
|
this.invokeMethod('create',
|
||||||
|
arguments, model, ctx, opts, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAll(model, data, opts, cb) {
|
||||||
|
const ctx = {data};
|
||||||
|
this.invokeMethod('createAll',
|
||||||
|
arguments, model, ctx, opts, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
save(model, data, opts, cb) {
|
||||||
|
const ctx = {data};
|
||||||
|
this.invokeMethod('save',
|
||||||
|
arguments, model, ctx, opts, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOrCreate(model, data, opts, cb) {
|
||||||
|
const ctx = {data};
|
||||||
|
this.invokeMethod('updateOrCreate',
|
||||||
|
arguments, model, ctx, opts, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceOrCreate(model, data, opts, cb) {
|
||||||
|
const ctx = {data};
|
||||||
|
this.invokeMethod('replaceOrCreate',
|
||||||
|
arguments, model, ctx, opts, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyAll(model, where, opts, cb) {
|
||||||
|
const ctx = {where};
|
||||||
|
this.invokeMethod('destroyAll',
|
||||||
|
arguments, model, ctx, opts, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(model, where, data, opts, cb) {
|
||||||
|
const ctx = {where, data};
|
||||||
|
this.invokeMethod('update',
|
||||||
|
arguments, model, ctx, opts, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceById(model, id, data, opts, cb) {
|
||||||
|
const ctx = {id, data};
|
||||||
|
this.invokeMethod('replaceById',
|
||||||
|
arguments, model, ctx, opts, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoggable(model) {
|
||||||
|
const Model = this.getModelDefinition(model).model;
|
||||||
|
const settings = Model.definition.settings;
|
||||||
|
return settings.base && settings.base === 'Loggable';
|
||||||
|
}
|
||||||
|
|
||||||
|
invokeMethod(method, args, model, ctx, opts, cb) {
|
||||||
|
if (!this.isLoggable(model))
|
||||||
|
return super[method].apply(this, args);
|
||||||
|
|
||||||
|
this.invokeMethodP(method, [...args], model, ctx, opts)
|
||||||
|
.then(res => cb(...res), cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
async invokeMethodP(method, args, model, ctx, opts) {
|
||||||
|
const Model = this.getModelDefinition(model).model;
|
||||||
|
const settings = Model.definition.settings;
|
||||||
|
let tx;
|
||||||
|
if (!opts.transaction) {
|
||||||
|
tx = await Transaction.begin(this, {});
|
||||||
|
opts = Object.assign({transaction: tx, httpCtx: opts.httpCtx}, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Fetch old values (update|delete) or login
|
||||||
|
let where, id, data, idName, limit, op, oldInstances, newInstances;
|
||||||
|
const hasGrabUser = settings.log && settings.log.grabUser;
|
||||||
|
if(hasGrabUser){
|
||||||
|
const userId = opts.httpCtx && opts.httpCtx.active.accessToken.userId;
|
||||||
|
const user = await Model.app.models.Account.findById(userId, {fields: ['name']}, opts);
|
||||||
|
await this.executeP(`CALL account.myUser_loginWithName(?)`, [user.name], opts);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
where = ctx.where;
|
||||||
|
id = ctx.id;
|
||||||
|
data = ctx.data;
|
||||||
|
idName = this.idName(model);
|
||||||
|
|
||||||
|
limit = limitSet.has(method);
|
||||||
|
|
||||||
|
op = opMap.get(method);
|
||||||
|
|
||||||
|
if (!where) {
|
||||||
|
if (id) where = {[idName]: id};
|
||||||
|
else where = {[idName]: data[idName]};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch old values
|
||||||
|
switch (op) {
|
||||||
|
case 'update':
|
||||||
|
case 'delete':
|
||||||
|
// Single entity operation
|
||||||
|
const stmt = this.buildSelectStmt(op, data, idName, model, where, limit);
|
||||||
|
stmt.merge(`FOR UPDATE`);
|
||||||
|
oldInstances = await this.executeStmt(stmt, opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await new Promise(resolve => {
|
||||||
|
const fnArgs = args.slice(0, -2);
|
||||||
|
fnArgs.push(opts, (...args) => resolve(args));
|
||||||
|
super[method].apply(this, fnArgs);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(hasGrabUser)
|
||||||
|
await this.executeP(`CALL account.myUser_logout()`, null, opts);
|
||||||
|
else {
|
||||||
|
// Fetch new values
|
||||||
|
const ids = [];
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case 'insert':
|
||||||
|
case 'update': {
|
||||||
|
switch (method) {
|
||||||
|
case 'createAll':
|
||||||
|
for (const row of res[1])
|
||||||
|
ids.push(row[idName]);
|
||||||
|
break;
|
||||||
|
case 'create':
|
||||||
|
ids.push(res[1]);
|
||||||
|
break;
|
||||||
|
case 'update':
|
||||||
|
if (data[idName] != null)
|
||||||
|
ids.push(data[idName]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newWhere = ids.length ? {[idName]: ids} : where;
|
||||||
|
|
||||||
|
const stmt = this.buildSelectStmt(op, data, idName, model, newWhere, limit);
|
||||||
|
newInstances = await this.executeStmt(stmt, opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.createLogRecord(oldInstances, newInstances, model, opts);
|
||||||
|
}
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
return res;
|
||||||
|
} catch (err) {
|
||||||
|
if (tx) tx.rollback();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buildSelectStmt(op, data, idName, model, where, limit) {
|
||||||
|
const Model = this.getModelDefinition(model).model;
|
||||||
|
const properties = Object.keys(Model.definition.properties);
|
||||||
|
|
||||||
|
const fields = data ? Object.keys(data) : [];
|
||||||
|
if (op == 'delete')
|
||||||
|
properties.forEach(property => fields.push(property));
|
||||||
|
else {
|
||||||
|
const log = Model.definition.settings.log;
|
||||||
|
fields.push(idName);
|
||||||
|
if (log.relation) fields.push(Model.relations[log.relation].keyFrom);
|
||||||
|
if (log.showField) fields.push(log.showField);
|
||||||
|
else {
|
||||||
|
const showFieldNames = ['name', 'description', 'code', 'nickname'];
|
||||||
|
for (const field of showFieldNames) {
|
||||||
|
if (properties.includes(field)) {
|
||||||
|
log.showField = field;
|
||||||
|
fields.push(field);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const stmt = new ParameterizedSQL(
|
||||||
|
'SELECT ' +
|
||||||
|
this.buildColumnNames(model, {fields}) +
|
||||||
|
' FROM ' +
|
||||||
|
this.tableEscaped(model)
|
||||||
|
);
|
||||||
|
stmt.merge(this.buildWhere(model, where));
|
||||||
|
if (limit) stmt.merge(`LIMIT 1`);
|
||||||
|
|
||||||
|
return stmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createLogRecord(oldInstances, newInstances, model, opts) {
|
||||||
|
function setActionType() {
|
||||||
|
if (oldInstances && newInstances)
|
||||||
|
return 'update';
|
||||||
|
else if (!oldInstances && newInstances)
|
||||||
|
return 'insert';
|
||||||
|
return 'delete';
|
||||||
|
}
|
||||||
|
|
||||||
|
const action = setActionType();
|
||||||
|
if (!newInstances && action != 'delete') return;
|
||||||
|
|
||||||
|
const Model = this.getModelDefinition(model).model;
|
||||||
|
const models = Model.app.models;
|
||||||
|
const definition = Model.definition;
|
||||||
|
const log = definition.settings.log;
|
||||||
|
|
||||||
|
const primaryKey = this.idName(model);
|
||||||
|
const originRelation = log.relation;
|
||||||
|
const originFkField = originRelation
|
||||||
|
? Model.relations[originRelation].keyFrom
|
||||||
|
: primaryKey;
|
||||||
|
|
||||||
|
// Prevent adding logs when deleting a principal entity (Client, Zone...)
|
||||||
|
if (action == 'delete' && !originRelation) return;
|
||||||
|
|
||||||
|
function map(instances) {
|
||||||
|
const map = new Map();
|
||||||
|
if (!instances) return;
|
||||||
|
for (const instance of instances)
|
||||||
|
map.set(instance[primaryKey], instance);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
const changedModel = definition.name;
|
||||||
|
const userFk = opts.httpCtx && opts.httpCtx.active.accessToken.userId;
|
||||||
|
const oldMap = map(oldInstances);
|
||||||
|
const newMap = map(newInstances);
|
||||||
|
const ids = (oldMap || newMap).keys();
|
||||||
|
|
||||||
|
const logEntries = [];
|
||||||
|
|
||||||
|
function insertValuesLogEntry(logEntry, instance) {
|
||||||
|
logEntry.originFk = instance[originFkField];
|
||||||
|
logEntry.changedModelId = instance[primaryKey];
|
||||||
|
if (log.showField) logEntry.changedModelValue = instance[log.showField];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const id of ids) {
|
||||||
|
const oldI = oldMap && oldMap.get(id);
|
||||||
|
const newI = newMap && newMap.get(id);
|
||||||
|
|
||||||
|
const logEntry = {
|
||||||
|
action,
|
||||||
|
userFk,
|
||||||
|
changedModel,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newI) {
|
||||||
|
insertValuesLogEntry(logEntry, newI);
|
||||||
|
// Delete unchanged properties
|
||||||
|
if (oldI) {
|
||||||
|
Object.keys(oldI).forEach(prop => {
|
||||||
|
const hasChanges = oldI[prop] instanceof Date ?
|
||||||
|
oldI[prop]?.getTime() != newI[prop]?.getTime() :
|
||||||
|
oldI[prop] != newI[prop];
|
||||||
|
|
||||||
|
if (!hasChanges) {
|
||||||
|
delete oldI[prop];
|
||||||
|
delete newI[prop];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
insertValuesLogEntry(logEntry, oldI);
|
||||||
|
|
||||||
|
logEntry.oldInstance = oldI;
|
||||||
|
logEntry.newInstance = newI;
|
||||||
|
logEntries.push(logEntry);
|
||||||
|
}
|
||||||
|
await models[log.model].create(logEntries, opts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.VnMySQL = VnMySQL;
|
exports.VnMySQL = VnMySQL;
|
||||||
|
|
|
@ -91,7 +91,11 @@ exports.getChanges = (original, changes) => {
|
||||||
const isPrivate = firstChar == '$';
|
const isPrivate = firstChar == '$';
|
||||||
if (isPrivate) return;
|
if (isPrivate) return;
|
||||||
|
|
||||||
if (changes[property] != original[property]) {
|
const hasChanges = original[property] instanceof Date ?
|
||||||
|
changes[property]?.getTime() != original[property]?.getTime() :
|
||||||
|
changes[property] != original[property];
|
||||||
|
|
||||||
|
if (hasChanges) {
|
||||||
newChanges[property] = changes[property];
|
newChanges[property] = changes[property];
|
||||||
|
|
||||||
if (original[property] != undefined)
|
if (original[property] != undefined)
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const { Report } = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('claimPickupPdf', {
|
Self.remoteMethodCtx('claimPickupPdf', {
|
||||||
description: 'Returns the claim pickup order pdf',
|
description: 'Returns the claim pickup order pdf',
|
||||||
|
@ -39,17 +37,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.claimPickupPdf = async(ctx, id) => {
|
Self.claimPickupPdf = (ctx, id) => Self.printReport(ctx, id, 'claim-pickup-order');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const report = new Report('claim-pickup-order', params);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
|
|
||||||
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('claim regularizeClaim()', () => {
|
describe('claim regularizeClaim()', () => {
|
||||||
const userId = 18;
|
const userId = 18;
|
||||||
|
@ -39,6 +40,20 @@ describe('claim regularizeClaim()', () => {
|
||||||
return await models.ClaimEnd.create(claimEnds, options);
|
return await models.ClaimEnd.create(claimEnds, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should send a chat message with value "Trash" and then change claim state to resolved', async() => {
|
it('should send a chat message with value "Trash" and then change claim state to resolved', async() => {
|
||||||
const tx = await models.Claim.beginTransaction({});
|
const tx = await models.Claim.beginTransaction({});
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,11 @@
|
||||||
"type": "hasMany",
|
"type": "hasMany",
|
||||||
"model": "ClaimDms",
|
"model": "ClaimDms",
|
||||||
"foreignKey": "claimFk"
|
"foreignKey": "claimFk"
|
||||||
|
},
|
||||||
|
"lines": {
|
||||||
|
"type": "hasMany",
|
||||||
|
"model": "ClaimBeginning",
|
||||||
|
"foreignKey": "claimFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,7 +86,20 @@
|
||||||
icon="icon-ticket">
|
icon="icon-ticket">
|
||||||
</vn-quick-link>
|
</vn-quick-link>
|
||||||
</div>
|
</div>
|
||||||
<div ng-transclude="btnThree"></div>
|
<div ng-transclude="btnThree">
|
||||||
|
<vn-quick-link
|
||||||
|
tooltip="Sale tracking"
|
||||||
|
state="['ticket.card.saleTracking', {id: $ctrl.claim.ticketFk}]"
|
||||||
|
icon="assignment">
|
||||||
|
</vn-quick-link>
|
||||||
|
</div>
|
||||||
|
<div ng-transclude="btnFour">
|
||||||
|
<vn-quick-link
|
||||||
|
tooltip="Ticket tracking"
|
||||||
|
state="['ticket.card.tracking.index', {id: $ctrl.claim.ticketFk}]"
|
||||||
|
icon="icon-eye">
|
||||||
|
</vn-quick-link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</slot-body>
|
</slot-body>
|
||||||
</vn-descriptor-content>
|
</vn-descriptor-content>
|
||||||
|
|
|
@ -151,7 +151,7 @@ class Controller extends Section {
|
||||||
isClaimEditable() {
|
isClaimEditable() {
|
||||||
if (!this.claim) return;
|
if (!this.claim) return;
|
||||||
|
|
||||||
this.$http.get(`ClaimStates/${this.claim.id}/isEditable`).then(res => {
|
this.$http.get(`ClaimStates/${this.claim.claimStateFk}/isEditable`).then(res => {
|
||||||
this.isRewritable = res.data;
|
this.isRewritable = res.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,8 @@ describe('claim', () => {
|
||||||
controller = $componentController('vnClaimDetail', {$element, $scope});
|
controller = $componentController('vnClaimDetail', {$element, $scope});
|
||||||
controller.claim = {
|
controller.claim = {
|
||||||
ticketFk: 1,
|
ticketFk: 1,
|
||||||
id: 2}
|
id: 2,
|
||||||
|
claimStateFk: 2}
|
||||||
;
|
;
|
||||||
controller.salesToClaim = [{saleFk: 1}, {saleFk: 2}];
|
controller.salesToClaim = [{saleFk: 1}, {saleFk: 2}];
|
||||||
controller.salesClaimed = [{id: 1, sale: {}}];
|
controller.salesClaimed = [{id: 1, sale: {}}];
|
||||||
|
|
|
@ -18,3 +18,5 @@ Claim deleted!: Reclamación eliminada!
|
||||||
claim: reclamación
|
claim: reclamación
|
||||||
Photos: Fotos
|
Photos: Fotos
|
||||||
Go to the claim: Ir a la reclamación
|
Go to the claim: Ir a la reclamación
|
||||||
|
Sale tracking: Líneas preparadas
|
||||||
|
Ticket tracking: Estados del ticket
|
||||||
|
|
|
@ -51,19 +51,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.campaignMetricsEmail = async ctx => {
|
Self.campaignMetricsEmail = ctx => Self.sendTemplate(ctx, 'campaign-metrics');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {
|
|
||||||
recipient: args.recipient,
|
|
||||||
lang: ctx.req.getLocale()
|
|
||||||
};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const email = new Email('campaign-metrics', params);
|
|
||||||
|
|
||||||
return email.send();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Report} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('campaignMetricsPdf', {
|
Self.remoteMethodCtx('campaignMetricsPdf', {
|
||||||
description: 'Returns the campaign metrics pdf',
|
description: 'Returns the campaign metrics pdf',
|
||||||
|
@ -50,17 +48,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.campaignMetricsPdf = async(ctx, id) => {
|
Self.campaignMetricsPdf = (ctx, id) => Self.printReport(ctx, id, 'campaign-metrics');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const report = new Report('campaign-metrics', params);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
|
|
||||||
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,19 +46,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.clientDebtStatementEmail = async ctx => {
|
Self.clientDebtStatementEmail = ctx => Self.sendTemplate(ctx, 'client-debt-statement');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {
|
|
||||||
recipient: args.recipient,
|
|
||||||
lang: ctx.req.getLocale()
|
|
||||||
};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const email = new Email('client-debt-statement', params);
|
|
||||||
|
|
||||||
return email.send();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('clientDebtStatementHtml', {
|
Self.remoteMethodCtx('clientDebtStatementHtml', {
|
||||||
description: 'Returns the client debt statement email preview',
|
description: 'Returns the client debt statement email preview',
|
||||||
|
@ -45,21 +43,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.clientDebtStatementHtml = async(ctx, id) => {
|
Self.clientDebtStatementHtml = (ctx, id) => Self.printEmail(ctx, id, 'client-debt-statement');
|
||||||
const {accessToken} = ctx.req;
|
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
params.isPreview = true;
|
|
||||||
params.access_token = accessToken.id;
|
|
||||||
|
|
||||||
const report = new Email('client-debt-statement', params);
|
|
||||||
const html = await report.render();
|
|
||||||
|
|
||||||
return [html, 'text/html', `filename="mail-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Report} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('clientDebtStatementPdf', {
|
Self.remoteMethodCtx('clientDebtStatementPdf', {
|
||||||
description: 'Returns the client debt statement pdf',
|
description: 'Returns the client debt statement pdf',
|
||||||
|
@ -45,17 +43,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.clientDebtStatementPdf = async(ctx, id) => {
|
Self.clientDebtStatementPdf = (ctx, id) => Self.printReport(ctx, id, 'client-debt-statement');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const report = new Report('client-debt-statement', params);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
|
|
||||||
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('clientWelcomeEmail', {
|
Self.remoteMethodCtx('clientWelcomeEmail', {
|
||||||
description: 'Sends the client welcome email with an attached PDF',
|
description: 'Sends the client welcome email with an attached PDF',
|
||||||
|
@ -41,19 +39,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.clientWelcomeEmail = async ctx => {
|
Self.clientWelcomeEmail = ctx => Self.sendTemplate(ctx, 'client-welcome');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {
|
|
||||||
recipient: args.recipient,
|
|
||||||
lang: ctx.req.getLocale()
|
|
||||||
};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const email = new Email('client-welcome', params);
|
|
||||||
|
|
||||||
return email.send();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('clientWelcomeHtml', {
|
Self.remoteMethodCtx('clientWelcomeHtml', {
|
||||||
description: 'Returns the client welcome email preview',
|
description: 'Returns the client welcome email preview',
|
||||||
|
@ -40,19 +38,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.clientWelcomeHtml = async(ctx, id) => {
|
Self.clientWelcomeHtml = (ctx, id) => Self.printEmail(ctx, id, 'client-welcome');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
params.isPreview = true;
|
|
||||||
|
|
||||||
const report = new Email('client-welcome', params);
|
|
||||||
const html = await report.render();
|
|
||||||
|
|
||||||
return [html, 'text/html', `filename="mail-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('clientCreditEmail', {
|
Self.remoteMethodCtx('clientCreditEmail', {
|
||||||
description: 'Sends the credit request email with an attached PDF',
|
description: 'Sends the credit request email with an attached PDF',
|
||||||
|
@ -10,7 +8,7 @@ module.exports = Self => {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'The client id',
|
description: 'The client id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'recipient',
|
arg: 'recipient',
|
||||||
|
@ -22,38 +20,25 @@ module.exports = Self => {
|
||||||
arg: 'replyTo',
|
arg: 'replyTo',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'The sender email to reply to',
|
description: 'The sender email to reply to',
|
||||||
required: false
|
required: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'recipientId',
|
arg: 'recipientId',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
description: 'The recipient id to send to the recipient preferred language',
|
description:
|
||||||
required: false
|
'The recipient id to send to the recipient preferred language',
|
||||||
}
|
required: false,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
type: ['object'],
|
type: ['object'],
|
||||||
root: true
|
root: true,
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
path: '/:id/credit-request-email',
|
path: '/:id/credit-request-email',
|
||||||
verb: 'POST'
|
verb: 'POST',
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.clientCreditEmail = async ctx => {
|
Self.clientCreditEmail = ctx => Self.sendTemplate(ctx, 'credit-request');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {
|
|
||||||
recipient: args.recipient,
|
|
||||||
lang: ctx.req.getLocale()
|
|
||||||
};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const email = new Email('credit-request', params);
|
|
||||||
|
|
||||||
return email.send();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('creditRequestHtml', {
|
Self.remoteMethodCtx('creditRequestHtml', {
|
||||||
description: 'Returns the credit request email preview',
|
description: 'Returns the credit request email preview',
|
||||||
|
@ -40,21 +38,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.creditRequestHtml = async(ctx, id) => {
|
Self.creditRequestHtml = (ctx, id) => Self.printEmail(ctx, id, 'credit-request');
|
||||||
const {accessToken} = ctx.req;
|
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
params.isPreview = true;
|
|
||||||
params.access_token = accessToken.id;
|
|
||||||
|
|
||||||
const report = new Email('credit-request', params);
|
|
||||||
const html = await report.render();
|
|
||||||
|
|
||||||
return [html, 'text/html', `filename="mail-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Report} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('creditRequestPdf', {
|
Self.remoteMethodCtx('creditRequestPdf', {
|
||||||
description: 'Returns the credit request pdf',
|
description: 'Returns the credit request pdf',
|
||||||
|
@ -40,17 +38,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.creditRequestPdf = async(ctx, id) => {
|
Self.creditRequestPdf = (ctx, id) => Self.printReport(ctx, id, 'credit-request');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const report = new Report('credit-request', params);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
|
|
||||||
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -80,7 +80,7 @@ module.exports = function(Self) {
|
||||||
const data = await Self.rawSql(query, [id, date], myOptions);
|
const data = await Self.rawSql(query, [id, date], myOptions);
|
||||||
|
|
||||||
client.debt = data[0].debt;
|
client.debt = data[0].debt;
|
||||||
client.unpaid = await Self.app.models.ClientUnpaid.findOne({id}, myOptions);
|
client.unpaid = await Self.app.models.ClientUnpaid.findById(id, null, myOptions);
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
|
|
||||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
|
||||||
|
|
||||||
module.exports = Self => {
|
|
||||||
Self.remoteMethod('getTransactions', {
|
|
||||||
description: 'Returns last entries',
|
|
||||||
accessType: 'READ',
|
|
||||||
accepts: [{
|
|
||||||
arg: 'filter',
|
|
||||||
type: 'object',
|
|
||||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
|
||||||
http: {source: 'query'}
|
|
||||||
}],
|
|
||||||
returns: {
|
|
||||||
type: ['object'],
|
|
||||||
root: true
|
|
||||||
},
|
|
||||||
http: {
|
|
||||||
path: `/getTransactions`,
|
|
||||||
verb: 'GET'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Self.getTransactions = async(filter, options) => {
|
|
||||||
const myOptions = {};
|
|
||||||
|
|
||||||
if (typeof options == 'object')
|
|
||||||
Object.assign(myOptions, options);
|
|
||||||
|
|
||||||
const conn = Self.dataSource.connector;
|
|
||||||
const stmt = new ParameterizedSQL(`
|
|
||||||
SELECT
|
|
||||||
t.id,
|
|
||||||
t.clientFk,
|
|
||||||
t.created,
|
|
||||||
t.amount / 100 amount,
|
|
||||||
t.receiptFk IS NOT NULL AS isConfirmed,
|
|
||||||
tt.message responseMessage,
|
|
||||||
te.message errorMessage
|
|
||||||
FROM hedera.tpvTransaction t
|
|
||||||
JOIN hedera.tpvMerchant m ON m.id = t.merchantFk
|
|
||||||
LEFT JOIN hedera.tpvResponse tt ON tt.id = t.response
|
|
||||||
LEFT JOIN hedera.tpvError te ON te.code = errorCode`);
|
|
||||||
|
|
||||||
stmt.merge(conn.makeSuffix(filter, 't'));
|
|
||||||
|
|
||||||
return Self.rawStmt(stmt, myOptions);
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('incotermsAuthorizationEmail', {
|
Self.remoteMethodCtx('incotermsAuthorizationEmail', {
|
||||||
description: 'Sends the incoterms authorization email with an attached PDF',
|
description: 'Sends the incoterms authorization email with an attached PDF',
|
||||||
|
@ -47,19 +45,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.incotermsAuthorizationEmail = async ctx => {
|
Self.incotermsAuthorizationEmail = ctx => Self.sendTemplate(ctx, 'incoterms-authorization');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {
|
|
||||||
recipient: args.recipient,
|
|
||||||
lang: ctx.req.getLocale()
|
|
||||||
};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const email = new Email('incoterms-authorization', params);
|
|
||||||
|
|
||||||
return email.send();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('incotermsAuthorizationHtml', {
|
Self.remoteMethodCtx('incotermsAuthorizationHtml', {
|
||||||
description: 'Returns the incoterms authorization email preview',
|
description: 'Returns the incoterms authorization email preview',
|
||||||
|
@ -46,21 +44,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.incotermsAuthorizationHtml = async(ctx, id) => {
|
Self.incotermsAuthorizationHtml = (ctx, id) => Self.printEmail(ctx, id, 'incoterms-authorization');
|
||||||
const {accessToken} = ctx.req;
|
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
params.isPreview = true;
|
|
||||||
params.access_token = accessToken.id;
|
|
||||||
|
|
||||||
const report = new Email('incoterms-authorization', params);
|
|
||||||
const html = await report.render();
|
|
||||||
|
|
||||||
return [html, 'text/html', `filename="mail-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Report} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('incotermsAuthorizationPdf', {
|
Self.remoteMethodCtx('incotermsAuthorizationPdf', {
|
||||||
description: 'Returns the incoterms authorization pdf',
|
description: 'Returns the incoterms authorization pdf',
|
||||||
|
@ -46,17 +44,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.incotermsAuthorizationPdf = async(ctx, id) => {
|
Self.incotermsAuthorizationPdf = (ctx, id) => Self.printReport(ctx, id, 'incoterms-authorization');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const report = new Report('incoterms-authorization', params);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
|
|
||||||
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('letterDebtorNdEmail', {
|
Self.remoteMethodCtx('letterDebtorNdEmail', {
|
||||||
description: 'Sends the second debtor letter email with an attached PDF',
|
description: 'Sends the second debtor letter email with an attached PDF',
|
||||||
|
@ -47,19 +45,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.letterDebtorNdEmail = async ctx => {
|
Self.letterDebtorNdEmail = ctx => Self.sendTemplate(ctx, 'letter-debtor-nd');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {
|
|
||||||
recipient: args.recipient,
|
|
||||||
lang: ctx.req.getLocale()
|
|
||||||
};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const email = new Email('letter-debtor-nd', params);
|
|
||||||
|
|
||||||
return email.send();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('letterDebtorNdHtml', {
|
Self.remoteMethodCtx('letterDebtorNdHtml', {
|
||||||
description: 'Returns the second letter debtor email preview',
|
description: 'Returns the second letter debtor email preview',
|
||||||
|
@ -46,21 +44,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.letterDebtorNdHtml = async(ctx, id) => {
|
Self.letterDebtorNdHtml = (ctx, id) => Self.printEmail(ctx, id, 'letter-debtor-nd');
|
||||||
const {accessToken} = ctx.req;
|
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
params.isPreview = true;
|
|
||||||
params.access_token = accessToken.id;
|
|
||||||
|
|
||||||
const report = new Email('letter-debtor-nd', params);
|
|
||||||
const html = await report.render();
|
|
||||||
|
|
||||||
return [html, 'text/html', `filename="mail-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Report} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('letterDebtorPdf', {
|
Self.remoteMethodCtx('letterDebtorPdf', {
|
||||||
description: 'Returns the letter debtor pdf',
|
description: 'Returns the letter debtor pdf',
|
||||||
|
@ -46,17 +44,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.letterDebtorPdf = async(ctx, id) => {
|
Self.letterDebtorPdf = (ctx, id) => Self.printReport(ctx, id, 'letter-debtor');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const report = new Report('letter-debtor', params);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
|
|
||||||
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('letterDebtorStEmail', {
|
Self.remoteMethodCtx('letterDebtorStEmail', {
|
||||||
description: 'Sends the printer setup email with an attached PDF',
|
description: 'Sends the printer setup email with an attached PDF',
|
||||||
|
@ -47,19 +45,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.letterDebtorStEmail = async ctx => {
|
Self.letterDebtorStEmail = ctx => Self.sendTemplate(ctx, 'letter-debtor-st');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {
|
|
||||||
recipient: args.recipient,
|
|
||||||
lang: ctx.req.getLocale()
|
|
||||||
};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const email = new Email('letter-debtor-st', params);
|
|
||||||
|
|
||||||
return email.send();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('letterDebtorStHtml', {
|
Self.remoteMethodCtx('letterDebtorStHtml', {
|
||||||
description: 'Returns the letter debtor email preview',
|
description: 'Returns the letter debtor email preview',
|
||||||
|
@ -46,21 +44,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.letterDebtorStHtml = async(ctx, id) => {
|
Self.letterDebtorStHtml = (ctx, id) => Self.printEmail(ctx, id, 'letter-debtor-st');
|
||||||
const {accessToken} = ctx.req;
|
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
params.isPreview = true;
|
|
||||||
params.access_token = accessToken.id;
|
|
||||||
|
|
||||||
const report = new Email('letter-debtor-st', params);
|
|
||||||
const html = await report.render();
|
|
||||||
|
|
||||||
return [html, 'text/html', `filename="mail-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('printerSetupEmail', {
|
Self.remoteMethodCtx('printerSetupEmail', {
|
||||||
description: 'Sends the printer setup email with an attached PDF',
|
description: 'Sends the printer setup email with an attached PDF',
|
||||||
|
@ -41,19 +39,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.printerSetupEmail = async ctx => {
|
Self.printerSetupEmail = ctx => Self.sendTemplate(ctx, 'printer-setup');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {
|
|
||||||
recipient: args.recipient,
|
|
||||||
lang: ctx.req.getLocale()
|
|
||||||
};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const email = new Email('printer-setup', params);
|
|
||||||
|
|
||||||
return email.send();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('printerSetupHtml', {
|
Self.remoteMethodCtx('printerSetupHtml', {
|
||||||
description: 'Returns the printer setup email preview',
|
description: 'Returns the printer setup email preview',
|
||||||
|
@ -40,19 +38,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.printerSetupHtml = async(ctx, id) => {
|
Self.printerSetupHtml = (ctx, id) => Self.printEmail(ctx, id, 'printer-setup');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
params.isPreview = true;
|
|
||||||
|
|
||||||
const report = new Email('printer-setup', params);
|
|
||||||
const html = await report.render();
|
|
||||||
|
|
||||||
return [html, 'text/html', `filename="mail-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('sepaCoreEmail', {
|
Self.remoteMethodCtx('sepaCoreEmail', {
|
||||||
description: 'Sends the campaign metrics email with an attached PDF',
|
description: 'Sends the campaign metrics email with an attached PDF',
|
||||||
|
@ -47,19 +45,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.sepaCoreEmail = async ctx => {
|
Self.sepaCoreEmail = ctx => Self.sendTemplate(ctx, 'sepa-core');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {
|
|
||||||
recipient: args.recipient,
|
|
||||||
lang: ctx.req.getLocale()
|
|
||||||
};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const email = new Email('sepa-core', params);
|
|
||||||
|
|
||||||
return email.send();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
|
||||||
|
|
||||||
describe('Client getTransations', () => {
|
|
||||||
it('should call getTransations() method to receive a list of Web Payments from Bruce Wayne', async() => {
|
|
||||||
const tx = await models.Client.beginTransaction({});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const options = {transaction: tx};
|
|
||||||
|
|
||||||
const filter = {where: {clientFk: 1101}};
|
|
||||||
const result = await models.Client.getTransactions(filter, options);
|
|
||||||
|
|
||||||
expect(result[1].id).toBeTruthy();
|
|
||||||
|
|
||||||
await tx.rollback();
|
|
||||||
} catch (e) {
|
|
||||||
await tx.rollback();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
|
describe('Client transactions', () => {
|
||||||
|
it('should call transactions() method to receive a list of Web Payments from Bruce Wayne', async() => {
|
||||||
|
const tx = await models.Client.beginTransaction({});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const ctx = {};
|
||||||
|
const filter = {where: {clientFk: 1101}};
|
||||||
|
const result = await models.Client.transactions(ctx, filter, options);
|
||||||
|
|
||||||
|
expect(result[1].id).toBeTruthy();
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call transactions() method filtering by orderFk', async() => {
|
||||||
|
const tx = await models.Client.beginTransaction({});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const ctx = {args: {orderFk: 6}};
|
||||||
|
const filter = {};
|
||||||
|
const result = await models.Client.transactions(ctx, filter, options);
|
||||||
|
|
||||||
|
const firstRow = result[0];
|
||||||
|
|
||||||
|
expect(result.length).toEqual(1);
|
||||||
|
expect(firstRow.id).toEqual(6);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call transactions() method filtering by amount', async() => {
|
||||||
|
const tx = await models.Client.beginTransaction({});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const ctx = {args: {amount: 40}};
|
||||||
|
const filter = {};
|
||||||
|
const result = await models.Client.transactions(ctx, filter, options);
|
||||||
|
|
||||||
|
const randomIndex = Math.floor(Math.random() * result.length);
|
||||||
|
const transaction = result[randomIndex];
|
||||||
|
|
||||||
|
expect(transaction.amount).toEqual(40);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,84 @@
|
||||||
|
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
|
const buildFilter = require('vn-loopback/util/filter').buildFilter;
|
||||||
|
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('transactions', {
|
||||||
|
description: 'Returns customer transactions',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'filter',
|
||||||
|
type: 'object',
|
||||||
|
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||||
|
http: {source: 'query'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'orderFk',
|
||||||
|
type: 'number',
|
||||||
|
http: {source: 'query'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'clientFk',
|
||||||
|
type: 'number',
|
||||||
|
http: {source: 'query'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'amount',
|
||||||
|
type: 'number',
|
||||||
|
http: {source: 'query'}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/transactions`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.transactions = async(ctx, filter, options) => {
|
||||||
|
const args = ctx.args;
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
const where = buildFilter(args, (param, value) => {
|
||||||
|
switch (param) {
|
||||||
|
case 'orderFk':
|
||||||
|
return {'t.id': value};
|
||||||
|
case 'clientFk':
|
||||||
|
return {'t.clientFk': value};
|
||||||
|
case 'amount':
|
||||||
|
return {'t.amount': (value * 100)};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
filter = mergeFilters(filter, {where});
|
||||||
|
|
||||||
|
const conn = Self.dataSource.connector;
|
||||||
|
const stmt = new ParameterizedSQL(`
|
||||||
|
SELECT
|
||||||
|
t.id,
|
||||||
|
t.clientFk,
|
||||||
|
c.name AS customerName,
|
||||||
|
t.created,
|
||||||
|
t.amount / 100 amount,
|
||||||
|
t.receiptFk IS NOT NULL AS isConfirmed,
|
||||||
|
tt.message responseMessage,
|
||||||
|
te.message errorMessage
|
||||||
|
FROM hedera.tpvTransaction t
|
||||||
|
JOIN client c ON c.id = t.clientFk
|
||||||
|
JOIN hedera.tpvMerchant m ON m.id = t.merchantFk
|
||||||
|
LEFT JOIN hedera.tpvResponse tt ON tt.id = t.response
|
||||||
|
LEFT JOIN hedera.tpvError te ON te.code = errorCode`);
|
||||||
|
|
||||||
|
stmt.merge(conn.makeSuffix(filter, 't'));
|
||||||
|
|
||||||
|
return Self.rawStmt(stmt, myOptions);
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,5 +1,3 @@
|
||||||
const { Report } = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('balanceCompensationPdf', {
|
Self.remoteMethodCtx('balanceCompensationPdf', {
|
||||||
description: 'Returns the the debit balances compensation pdf',
|
description: 'Returns the the debit balances compensation pdf',
|
||||||
|
@ -10,7 +8,7 @@ module.exports = Self => {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'The receipt id',
|
description: 'The receipt id',
|
||||||
http: { source: 'path' }
|
http: {source: 'path'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: [
|
returns: [
|
||||||
|
@ -34,17 +32,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.balanceCompensationPdf = async(ctx, id) => {
|
Self.balanceCompensationPdf = (ctx, id) => Self.printReport(ctx, id, 'balance-compensation');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const report = new Report('balance-compensation', params);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
|
|
||||||
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Report} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('receiptPdf', {
|
Self.remoteMethodCtx('receiptPdf', {
|
||||||
description: 'Returns the receipt pdf',
|
description: 'Returns the receipt pdf',
|
||||||
|
@ -39,17 +37,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.receiptPdf = async(ctx, id) => {
|
Self.receiptPdf = (ctx, id) => Self.printReport(ctx, id, 'receipt');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const report = new Report('receipt', params);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
|
|
||||||
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,7 @@ module.exports = Self => {
|
||||||
require('../methods/client/getCard')(Self);
|
require('../methods/client/getCard')(Self);
|
||||||
require('../methods/client/getDebt')(Self);
|
require('../methods/client/getDebt')(Self);
|
||||||
require('../methods/client/getMana')(Self);
|
require('../methods/client/getMana')(Self);
|
||||||
require('../methods/client/getTransactions')(Self);
|
require('../methods/client/transactions')(Self);
|
||||||
require('../methods/client/hasCustomerRole')(Self);
|
require('../methods/client/hasCustomerRole')(Self);
|
||||||
require('../methods/client/isValidClient')(Self);
|
require('../methods/client/isValidClient')(Self);
|
||||||
require('../methods/client/lastActiveTickets')(Self);
|
require('../methods/client/lastActiveTickets')(Self);
|
||||||
|
|
|
@ -279,6 +279,18 @@ module.exports = Self => {
|
||||||
// Credit changes
|
// Credit changes
|
||||||
if (changes.credit !== undefined)
|
if (changes.credit !== undefined)
|
||||||
await Self.changeCredit(ctx, finalState, changes);
|
await Self.changeCredit(ctx, finalState, changes);
|
||||||
|
|
||||||
|
const oldInstance = {};
|
||||||
|
if (!ctx.isNewInstance) {
|
||||||
|
const newProps = Object.keys(changes);
|
||||||
|
Object.keys(orgData.__data).forEach(prop => {
|
||||||
|
if (newProps.includes(prop))
|
||||||
|
oldInstance[prop] = orgData[prop];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.hookState.oldInstance = oldInstance;
|
||||||
|
ctx.hookState.newInstance = changes;
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.observe('after save', async ctx => {
|
Self.observe('after save', async ctx => {
|
||||||
|
|
|
@ -154,6 +154,11 @@
|
||||||
"model": "Account",
|
"model": "Account",
|
||||||
"foreignKey": "id"
|
"foreignKey": "id"
|
||||||
},
|
},
|
||||||
|
"user": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Account",
|
||||||
|
"foreignKey": "id"
|
||||||
|
},
|
||||||
"payMethod": {
|
"payMethod": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "PayMethod",
|
"model": "PayMethod",
|
||||||
|
|
|
@ -62,6 +62,11 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Bank",
|
"model": "Bank",
|
||||||
"foreignKey": "bankFk"
|
"foreignKey": "bankFk"
|
||||||
|
},
|
||||||
|
"supplier": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Supplier",
|
||||||
|
"foreignKey": "companyFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -70,11 +70,12 @@
|
||||||
icon="icon-no036"
|
icon="icon-no036"
|
||||||
ng-if="$ctrl.client.isTaxDataChecked == false">
|
ng-if="$ctrl.client.isTaxDataChecked == false">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
<vn-icon
|
<vn-icon-button
|
||||||
vn-tooltip="{{$ctrl.clientUnpaid()}}"
|
vn-tooltip="{{$ctrl.clientUnpaid()}}"
|
||||||
icon="icon-clientUnpaid"
|
icon="icon-clientUnpaid"
|
||||||
|
ui-sref="client.card.unpaid"
|
||||||
ng-if="$ctrl.client.unpaid">
|
ng-if="$ctrl.client.unpaid">
|
||||||
</vn-icon>
|
</vn-icon-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="quicklinks">
|
<div class="quicklinks">
|
||||||
<div ng-transclude="btnOne">
|
<div ng-transclude="btnOne">
|
||||||
|
|
|
@ -46,8 +46,9 @@ class Controller extends Descriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
clientUnpaid() {
|
clientUnpaid() {
|
||||||
return this.$t(`Unpaid Dated`, {dated: this.client.unpaid.dated}) +
|
return this.$t(`Unpaid`) + '<br/>'
|
||||||
'<br/>' + this.$t(`Unpaid Amount`, {amount: this.client.unpaid.amount});
|
+ this.$t(`Unpaid Dated`, {dated: this.client.unpaid.dated}) + '<br/>'
|
||||||
|
+ this.$t(`Unpaid Amount`, {amount: this.client.unpaid.amount});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
<form
|
<form
|
||||||
name="form"
|
name="form"
|
||||||
ng-submit="watcher.submit()"
|
ng-submit="$ctrl.onSubmit()"
|
||||||
class="vn-w-md">
|
class="vn-w-md">
|
||||||
<vn-card class="vn-pa-lg">
|
<vn-card class="vn-pa-lg">
|
||||||
<vn-vertical>
|
<vn-vertical>
|
||||||
|
|
|
@ -6,9 +6,17 @@ export default class Controller extends Section {
|
||||||
if (hasData && !this.clientUnpaid.dated)
|
if (hasData && !this.clientUnpaid.dated)
|
||||||
this.clientUnpaid.dated = Date.vnNew();
|
this.clientUnpaid.dated = Date.vnNew();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
this.$.watcher.submit()
|
||||||
|
.then(() => this.card.reload());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngModule.vnComponent('vnClientUnpaid', {
|
ngModule.vnComponent('vnClientUnpaid', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Controller
|
controller: Controller,
|
||||||
|
require: {
|
||||||
|
card: '^vnClientCard'
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,15 +1,7 @@
|
||||||
<vn-crud-model
|
<vn-crud-model vn-id="model" url="clients/transactions" link="{clientFk: $ctrl.$params.id}" limit="20"
|
||||||
vn-id="model"
|
data="transactions" order="created DESC" auto-load="true">
|
||||||
url="clients/getTransactions"
|
|
||||||
link="{clientFk: $ctrl.$params.id}"
|
|
||||||
limit="20"
|
|
||||||
data="transactions"
|
|
||||||
order="created DESC"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-data-viewer
|
<vn-data-viewer model="model" class="vn-w-md">
|
||||||
model="model"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card>
|
<vn-card>
|
||||||
<vn-table model="model">
|
<vn-table model="model">
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
|
@ -24,27 +16,19 @@
|
||||||
<vn-tbody>
|
<vn-tbody>
|
||||||
<vn-tr ng-repeat="transaction in transactions">
|
<vn-tr ng-repeat="transaction in transactions">
|
||||||
<vn-td shrink>
|
<vn-td shrink>
|
||||||
<vn-icon
|
<vn-icon vn-tooltip="{{::$ctrl.getFormattedMessage(transaction)}}"
|
||||||
vn-tooltip="{{::$ctrl.getFormattedMessage(transaction)}}"
|
|
||||||
ng-show="::((transaction.errorMessage || transaction.responseMessage) && !transaction.isConfirmed)"
|
ng-show="::((transaction.errorMessage || transaction.responseMessage) && !transaction.isConfirmed)"
|
||||||
icon="clear">
|
icon="clear">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
<vn-icon
|
<vn-icon vn-tooltip="Confirmed" ng-show="::(transaction.isConfirmed)" icon="check">
|
||||||
vn-tooltip="Confirmed"
|
|
||||||
ng-show="::(transaction.isConfirmed)"
|
|
||||||
icon="check">
|
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::transaction.id}}</vn-td>
|
<vn-td number>{{::transaction.id}}</vn-td>
|
||||||
<vn-td>{{::transaction.created | date:'dd/MM/yyyy HH:mm'}}</vn-td>
|
<vn-td>{{::transaction.created | date:'dd/MM/yyyy HH:mm'}}</vn-td>
|
||||||
<vn-td number>{{::transaction.amount | currency: 'EUR':2}}</vn-td>
|
<vn-td number>{{::transaction.amount | currency: 'EUR':2}}</vn-td>
|
||||||
<vn-td shrink>
|
<vn-td shrink>
|
||||||
<vn-icon-button
|
<vn-icon-button icon="done_all" vn-acl="administrative" vn-acl-action="remove"
|
||||||
icon="done_all"
|
translate-attr="{title: 'Confirm transaction'}" ng-show="::!transaction.isConfirmed"
|
||||||
vn-acl="administrative"
|
|
||||||
vn-acl-action="remove"
|
|
||||||
translate-attr="{title: 'Confirm transaction'}"
|
|
||||||
ng-show="::!transaction.isConfirmed"
|
|
||||||
ng-click="$ctrl.confirm(transaction)">
|
ng-click="$ctrl.confirm(transaction)">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Report} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('entryOrderPdf', {
|
Self.remoteMethodCtx('entryOrderPdf', {
|
||||||
description: 'Returns the entry order pdf',
|
description: 'Returns the entry order pdf',
|
||||||
|
@ -38,17 +36,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.entryOrderPdf = async(ctx, id) => {
|
Self.entryOrderPdf = (ctx, id) => Self.printReport(ctx, id, 'entry-order');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const report = new Report('entry-order', params);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
|
|
||||||
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,22 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('Buy editLatestsBuys()', () => {
|
describe('Buy editLatestsBuys()', () => {
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 9},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should change the value of a given column for the selected buys', async() => {
|
it('should change the value of a given column for the selected buys', async() => {
|
||||||
const tx = await models.Buy.beginTransaction({});
|
const tx = await models.Buy.beginTransaction({});
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
"base": "Loggable",
|
"base": "Loggable",
|
||||||
"log": {
|
"log": {
|
||||||
"model": "EntryLog",
|
"model": "EntryLog",
|
||||||
"relation": "entry"
|
"relation": "entry",
|
||||||
|
"grabUser": true
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
"name": "Entry",
|
"name": "Entry",
|
||||||
"base": "Loggable",
|
"base": "Loggable",
|
||||||
"log": {
|
"log": {
|
||||||
"model":"EntryLog"
|
"model":"EntryLog",
|
||||||
|
"grabUser": true
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Email} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('invoiceInEmail', {
|
Self.remoteMethodCtx('invoiceInEmail', {
|
||||||
description: 'Sends the invoice in email with an attached PDF',
|
description: 'Sends the invoice in email with an attached PDF',
|
||||||
|
@ -35,19 +33,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.invoiceInEmail = async ctx => {
|
Self.invoiceInEmail = ctx => Self.sendTemplate(ctx, 'invoiceIn');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {
|
|
||||||
recipient: args.recipient,
|
|
||||||
lang: ctx.req.getLocale()
|
|
||||||
};
|
|
||||||
|
|
||||||
delete args.ctx;
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const email = new Email('invoiceIn', params);
|
|
||||||
|
|
||||||
return email.send();
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
const {Report} = require('vn-print');
|
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('invoiceInPdf', {
|
Self.remoteMethodCtx('invoiceInPdf', {
|
||||||
description: 'Returns the invoiceIn pdf',
|
description: 'Returns the invoiceIn pdf',
|
||||||
|
@ -34,17 +32,5 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.invoiceInPdf = async(ctx, id) => {
|
Self.invoiceInPdf = (ctx, id) => Self.printReport(ctx, id, 'invoiceIn');
|
||||||
const args = Object.assign({}, ctx.args);
|
|
||||||
const params = {lang: ctx.req.getLocale()};
|
|
||||||
delete args.ctx;
|
|
||||||
|
|
||||||
for (const param in args)
|
|
||||||
params[param] = args[param];
|
|
||||||
|
|
||||||
const report = new Report('invoiceIn', params);
|
|
||||||
const stream = await report.toPdfStream();
|
|
||||||
|
|
||||||
return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue