diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf7d8465a..dde790aaa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,16 +5,24 @@ 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/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [2312.01] - 2023-04-06
+
+### Added
+-
+
+### Changed
+-
+
+### Fixed
+-
+
## [2310.01] - 2023-03-23
### Added
--
-
-### Changed
--
+- (Trabajadores -> Control de horario) Ahora se puede confirmar/no confirmar el registro horario de cada semana desde esta sección
### 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"
- (General) Al pasar el ratón por encima del icono de "Borrar" en un campo, se hacía más grande afectando a la interfaz
## [2308.01] - 2023-03-09
diff --git a/Dockerfile b/Dockerfile
index a59725f77..ee87cd0d0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -10,6 +10,7 @@ RUN apt-get update \
curl \
ca-certificates \
gnupg2 \
+ graphicsmagick \
&& curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \
&& apt-get install -y --no-install-recommends nodejs \
&& npm install -g npm@8.19.2
diff --git a/back/methods/collection/previousLabel.js b/back/methods/collection/previousLabel.js
index fb2df8133..e3dac1ab4 100644
--- a/back/methods/collection/previousLabel.js
+++ b/back/methods/collection/previousLabel.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('previousLabel', {
description: 'Returns the previa label pdf',
@@ -33,17 +31,5 @@ module.exports = Self => {
}
});
- Self.previousLabel = async(ctx, id) => {
- 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"`];
- };
+ Self.previousLabel = (ctx, id) => Self.printReport(ctx, id, 'previa-label');
};
diff --git a/back/methods/dms/saveSign.js b/back/methods/dms/saveSign.js
deleted file mode 100644
index ed462a301..000000000
--- a/back/methods/dms/saveSign.js
+++ /dev/null
@@ -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;
- }
- };
-};
diff --git a/back/models/delivery.json b/back/models/delivery.json
index 65a0eef1b..c66c31b45 100644
--- a/back/models/delivery.json
+++ b/back/models/delivery.json
@@ -9,17 +9,29 @@
"properties": {
"id": {
"id": true,
- "type": "number",
- "forceId": false
+ "type": "number"
},
- "date": {
+ "created": {
"type": "date"
},
- "m3":{
+ "longitude":{
"type": "number"
},
- "warehouseFk":{
+ "latitude":{
+ "type": "number"
+ },
+ "dated":{
+ "type": "date"
+ },
+ "ticketFk":{
"type": "number"
}
- }
+ },
+ "relations": {
+ "ticket": {
+ "type": "belongsTo",
+ "model": "Ticket",
+ "foreignKey": "ticketFk"
+ }
+ }
}
diff --git a/back/models/dms.js b/back/models/dms.js
index fc586201f..24c072f56 100644
--- a/back/models/dms.js
+++ b/back/models/dms.js
@@ -6,7 +6,6 @@ module.exports = Self => {
require('../methods/dms/removeFile')(Self);
require('../methods/dms/updateFile')(Self);
require('../methods/dms/deleteTrashFiles')(Self);
- require('../methods/dms/saveSign')(Self);
Self.checkRole = async function(ctx, id) {
const models = Self.app.models;
diff --git a/db/changes/231001/00-delivery.sql b/db/changes/231001/00-delivery.sql
new file mode 100644
index 000000000..3a9269183
--- /dev/null
+++ b/db/changes/231001/00-delivery.sql
@@ -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 ;
diff --git a/db/changes/231001/.gitkeep b/db/changes/231201/.gitkeep
similarity index 100%
rename from db/changes/231001/.gitkeep
rename to db/changes/231201/.gitkeep
diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql
index a0c72d726..3ab34e1d5 100644
--- a/db/dump/fixtures.sql
+++ b/db/dump/fixtures.sql
@@ -2825,4 +2825,11 @@ INSERT INTO `vn`.`deviceProductionUser` (`deviceProductionFk`, `userFk`, `create
(1, 1, 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);
+
diff --git a/db/dump/structure.sql b/db/dump/structure.sql
index 63754d536..90e4c4bc9 100644
--- a/db/dump/structure.sql
+++ b/db/dump/structure.sql
@@ -81220,3 +81220,4 @@ USE `vn`;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2023-02-21 8:14:30
+
diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js
index 2ace69567..f20d75310 100644
--- a/e2e/helpers/selectors.js
+++ b/e2e/helpers/selectors.js
@@ -524,7 +524,7 @@ export default {
},
itemLog: {
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',
+ fifthLineCreatedProperty: 'vn-item-log > vn-log vn-tbody > vn-tr:nth-child(5) table tr:nth-child(4) td.after',
},
ticketSummary: {
header: 'vn-ticket-summary > vn-card > h5',
diff --git a/e2e/paths/04-item/10_item_log.spec.js b/e2e/paths/04-item/10_item_log.spec.js
index 2a885fe6f..46979a761 100644
--- a/e2e/paths/04-item/10_item_log.spec.js
+++ b/e2e/paths/04-item/10_item_log.spec.js
@@ -59,6 +59,6 @@ describe('Item log path', () => {
const fifthLineCreatedProperty = await page
.waitToGetProperty(selectors.itemLog.fifthLineCreatedProperty, 'innerText');
- expect(fifthLineCreatedProperty).toEqual('Coral y materiales similares');
+ expect(fifthLineCreatedProperty).toEqual('05080000');
});
});
diff --git a/e2e/paths/11-zone/02_descriptor.spec.js b/e2e/paths/11-zone/02_descriptor.spec.js
index 1de84d601..12a1c8f68 100644
--- a/e2e/paths/11-zone/02_descriptor.spec.js
+++ b/e2e/paths/11-zone/02_descriptor.spec.js
@@ -37,6 +37,6 @@ describe('Zone descriptor path', () => {
await page.accessToSection('ticket.card.log');
const lastChanges = await page.waitToGetProperty(selectors.ticketLog.changes, 'innerText');
- expect(lastChanges).toContain('Arreglar');
+ expect(lastChanges).toContain('1');
});
});
diff --git a/front/core/components/calendar/index.html b/front/core/components/calendar/index.html
index 086fe4338..4d02f9ec0 100644
--- a/front/core/components/calendar/index.html
+++ b/front/core/components/calendar/index.html
@@ -24,7 +24,7 @@
@@ -57,4 +57,4 @@
-
\ No newline at end of file
+
diff --git a/front/core/components/calendar/index.js b/front/core/components/calendar/index.js
index 17ccbf041..0e39267a7 100644
--- a/front/core/components/calendar/index.js
+++ b/front/core/components/calendar/index.js
@@ -15,9 +15,9 @@ export default class Calendar extends FormInput {
constructor($element, $scope, vnWeekDays, moment) {
super($element, $scope);
this.weekDays = vnWeekDays.locales;
- this.defaultDate = Date.vnNew();
this.displayControls = true;
this.moment = moment;
+ this.defaultDate = Date.vnNew();
}
/**
@@ -207,14 +207,23 @@ export default class Calendar extends FormInput {
}
repeatLast() {
- if (!this.formatDay) return;
+ if (this.formatDay) {
+ const days = this.element.querySelectorAll('.days > .day');
+ for (let i = 0; i < days.length; i++) {
+ this.formatDay({
+ $day: this.days[i],
+ $element: days[i]
+ });
+ }
+ }
- let days = this.element.querySelectorAll('.days > .day');
- for (let i = 0; i < days.length; i++) {
- this.formatDay({
- $day: this.days[i],
- $element: days[i]
- });
+ if (this.formatWeek) {
+ const weeks = this.element.querySelectorAll('.weeks > .day');
+ for (const week of weeks) {
+ this.formatWeek({
+ $element: week
+ });
+ }
}
}
}
@@ -228,6 +237,7 @@ ngModule.vnComponent('vnCalendar', {
hasEvents: '&?',
getClass: '&?',
formatDay: '&?',
+ formatWeek: '&?',
displayControls: '',
hideYear: '',
hideContiguous: '',
diff --git a/loopback/common/methods/vn-model/printService.js b/loopback/common/methods/vn-model/printService.js
new file mode 100644
index 000000000..5cd571d4c
--- /dev/null
+++ b/loopback/common/methods/vn-model/printService.js
@@ -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();
+ };
+};
diff --git a/loopback/common/models/loggable.js b/loopback/common/models/loggable.js
index 28a6075d0..360c84566 100644
--- a/loopback/common/models/loggable.js
+++ b/loopback/common/models/loggable.js
@@ -1,4 +1,3 @@
-const pick = require('object.pick');
const LoopBackContext = require('loopback-context');
module.exports = function(Self) {
@@ -6,344 +5,11 @@ module.exports = function(Self) {
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) {
- const appModels = ctx.Model.app.models;
- 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;
+ ctx.options.httpCtx = LoopBackContext.getCurrentContext();
});
Self.observe('before delete', async function(ctx) {
- const appModels = ctx.Model.app.models;
- 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;
- }
- }
+ ctx.options.httpCtx = LoopBackContext.getCurrentContext();
});
-
- 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';
- }
};
diff --git a/loopback/common/models/vn-model.js b/loopback/common/models/vn-model.js
index cc3eede8e..cebd37eac 100644
--- a/loopback/common/models/vn-model.js
+++ b/loopback/common/models/vn-model.js
@@ -7,6 +7,7 @@ module.exports = function(Self) {
require('../methods/vn-model/getSetValues')(Self);
require('../methods/vn-model/getEnumValues')(Self);
+ require('../methods/vn-model/printService')(Self);
Object.assign(Self, {
setup() {
diff --git a/loopback/locale/es.json b/loopback/locale/es.json
index 788c2fa96..95bf16d66 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -270,5 +270,6 @@
"Warehouse inventory not set": "El almacén inventario no está establecido",
"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}}",
- "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"
}
diff --git a/loopback/server/connectors/vn-mysql.js b/loopback/server/connectors/vn-mysql.js
index fde0ddcf6..5c1ceaa32 100644
--- a/loopback/server/connectors/vn-mysql.js
+++ b/loopback/server/connectors/vn-mysql.js
@@ -2,8 +2,41 @@ const mysql = require('mysql');
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const MySQL = require('loopback-connector-mysql').MySQL;
const EnumFactory = require('loopback-connector-mysql').EnumFactory;
+const Transaction = require('loopback-connector').Transaction;
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 {
/**
* Promisified version of execute().
@@ -219,6 +252,277 @@ class VnMySQL extends MySQL {
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;
diff --git a/loopback/util/log.js b/loopback/util/log.js
index e26022c35..76e87781d 100644
--- a/loopback/util/log.js
+++ b/loopback/util/log.js
@@ -91,7 +91,11 @@ exports.getChanges = (original, changes) => {
const isPrivate = firstChar == '$';
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];
if (original[property] != undefined)
diff --git a/modules/claim/back/methods/claim/claimPickupPdf.js b/modules/claim/back/methods/claim/claimPickupPdf.js
index 0e3abe908..4927efa0f 100644
--- a/modules/claim/back/methods/claim/claimPickupPdf.js
+++ b/modules/claim/back/methods/claim/claimPickupPdf.js
@@ -1,5 +1,3 @@
-const { Report } = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('claimPickupPdf', {
description: 'Returns the claim pickup order pdf',
@@ -39,17 +37,5 @@ module.exports = Self => {
}
});
- Self.claimPickupPdf = async(ctx, id) => {
- 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"`];
- };
+ Self.claimPickupPdf = (ctx, id) => Self.printReport(ctx, id, 'claim-pickup-order');
};
diff --git a/modules/claim/front/descriptor/index.html b/modules/claim/front/descriptor/index.html
index f346ecf17..5fd198440 100644
--- a/modules/claim/front/descriptor/index.html
+++ b/modules/claim/front/descriptor/index.html
@@ -86,7 +86,20 @@
icon="icon-ticket">
-
+
+
+
+
+
+
+
+
diff --git a/modules/claim/front/locale/es.yml b/modules/claim/front/locale/es.yml
index 5abdc1535..419e62f56 100644
--- a/modules/claim/front/locale/es.yml
+++ b/modules/claim/front/locale/es.yml
@@ -18,3 +18,5 @@ Claim deleted!: Reclamación eliminada!
claim: reclamación
Photos: Fotos
Go to the claim: Ir a la reclamación
+Sale tracking: Líneas preparadas
+Ticket tracking: Estados del ticket
diff --git a/modules/client/back/methods/client/campaignMetricsEmail.js b/modules/client/back/methods/client/campaignMetricsEmail.js
index bb57f90a0..3a1bac5e6 100644
--- a/modules/client/back/methods/client/campaignMetricsEmail.js
+++ b/modules/client/back/methods/client/campaignMetricsEmail.js
@@ -51,19 +51,5 @@ module.exports = Self => {
}
});
- Self.campaignMetricsEmail = async ctx => {
- 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();
- };
+ Self.campaignMetricsEmail = ctx => Self.sendTemplate(ctx, 'campaign-metrics');
};
diff --git a/modules/client/back/methods/client/campaignMetricsPdf.js b/modules/client/back/methods/client/campaignMetricsPdf.js
index 14194d62b..e163b0619 100644
--- a/modules/client/back/methods/client/campaignMetricsPdf.js
+++ b/modules/client/back/methods/client/campaignMetricsPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('campaignMetricsPdf', {
description: 'Returns the campaign metrics pdf',
@@ -50,17 +48,5 @@ module.exports = Self => {
}
});
- Self.campaignMetricsPdf = async(ctx, id) => {
- 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"`];
- };
+ Self.campaignMetricsPdf = (ctx, id) => Self.printReport(ctx, id, 'campaign-metrics');
};
diff --git a/modules/client/back/methods/client/clientDebtStatementEmail.js b/modules/client/back/methods/client/clientDebtStatementEmail.js
index 8bcdc900f..1b3ab13d8 100644
--- a/modules/client/back/methods/client/clientDebtStatementEmail.js
+++ b/modules/client/back/methods/client/clientDebtStatementEmail.js
@@ -46,19 +46,5 @@ module.exports = Self => {
}
});
- Self.clientDebtStatementEmail = async ctx => {
- 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();
- };
+ Self.clientDebtStatementEmail = ctx => Self.sendTemplate(ctx, 'client-debt-statement');
};
diff --git a/modules/client/back/methods/client/clientDebtStatementHtml.js b/modules/client/back/methods/client/clientDebtStatementHtml.js
index bfed696bc..8752b48d2 100644
--- a/modules/client/back/methods/client/clientDebtStatementHtml.js
+++ b/modules/client/back/methods/client/clientDebtStatementHtml.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('clientDebtStatementHtml', {
description: 'Returns the client debt statement email preview',
@@ -45,21 +43,5 @@ module.exports = Self => {
}
});
- Self.clientDebtStatementHtml = async(ctx, id) => {
- 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"`];
- };
+ Self.clientDebtStatementHtml = (ctx, id) => Self.printEmail(ctx, id, 'client-debt-statement');
};
diff --git a/modules/client/back/methods/client/clientDebtStatementPdf.js b/modules/client/back/methods/client/clientDebtStatementPdf.js
index 8e2dca314..845527ace 100644
--- a/modules/client/back/methods/client/clientDebtStatementPdf.js
+++ b/modules/client/back/methods/client/clientDebtStatementPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('clientDebtStatementPdf', {
description: 'Returns the client debt statement pdf',
@@ -45,17 +43,5 @@ module.exports = Self => {
}
});
- Self.clientDebtStatementPdf = async(ctx, id) => {
- 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"`];
- };
+ Self.clientDebtStatementPdf = (ctx, id) => Self.printReport(ctx, id, 'client-debt-statement');
};
diff --git a/modules/client/back/methods/client/clientWelcomeEmail.js b/modules/client/back/methods/client/clientWelcomeEmail.js
index 318ee18e6..accf12bb8 100644
--- a/modules/client/back/methods/client/clientWelcomeEmail.js
+++ b/modules/client/back/methods/client/clientWelcomeEmail.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('clientWelcomeEmail', {
description: 'Sends the client welcome email with an attached PDF',
@@ -41,19 +39,5 @@ module.exports = Self => {
}
});
- Self.clientWelcomeEmail = async ctx => {
- 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();
- };
+ Self.clientWelcomeEmail = ctx => Self.sendTemplate(ctx, 'client-welcome');
};
diff --git a/modules/client/back/methods/client/clientWelcomeHtml.js b/modules/client/back/methods/client/clientWelcomeHtml.js
index dfb560326..093a06d8e 100644
--- a/modules/client/back/methods/client/clientWelcomeHtml.js
+++ b/modules/client/back/methods/client/clientWelcomeHtml.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('clientWelcomeHtml', {
description: 'Returns the client welcome email preview',
@@ -40,19 +38,5 @@ module.exports = Self => {
}
});
- Self.clientWelcomeHtml = async(ctx, id) => {
- 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"`];
- };
+ Self.clientWelcomeHtml = (ctx, id) => Self.printEmail(ctx, id, 'client-welcome');
};
diff --git a/modules/client/back/methods/client/creditRequestEmail.js b/modules/client/back/methods/client/creditRequestEmail.js
index b6a60e971..0255949e0 100644
--- a/modules/client/back/methods/client/creditRequestEmail.js
+++ b/modules/client/back/methods/client/creditRequestEmail.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('clientCreditEmail', {
description: 'Sends the credit request email with an attached PDF',
@@ -10,7 +8,7 @@ module.exports = Self => {
type: 'number',
required: true,
description: 'The client id',
- http: {source: 'path'}
+ http: {source: 'path'},
},
{
arg: 'recipient',
@@ -22,38 +20,25 @@ module.exports = Self => {
arg: 'replyTo',
type: 'string',
description: 'The sender email to reply to',
- required: false
+ required: false,
},
{
arg: 'recipientId',
type: 'number',
- description: 'The recipient id to send to the recipient preferred language',
- required: false
- }
+ description:
+ 'The recipient id to send to the recipient preferred language',
+ required: false,
+ },
],
returns: {
type: ['object'],
- root: true
+ root: true,
},
http: {
path: '/:id/credit-request-email',
- verb: 'POST'
- }
+ verb: 'POST',
+ },
});
- Self.clientCreditEmail = async ctx => {
- 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();
- };
+ Self.clientCreditEmail = ctx => Self.sendTemplate(ctx, 'credit-request');
};
diff --git a/modules/client/back/methods/client/creditRequestHtml.js b/modules/client/back/methods/client/creditRequestHtml.js
index 6b2d7fe4e..fbd6cacb9 100644
--- a/modules/client/back/methods/client/creditRequestHtml.js
+++ b/modules/client/back/methods/client/creditRequestHtml.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('creditRequestHtml', {
description: 'Returns the credit request email preview',
@@ -40,21 +38,5 @@ module.exports = Self => {
}
});
- Self.creditRequestHtml = async(ctx, id) => {
- 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"`];
- };
+ Self.creditRequestHtml = (ctx, id) => Self.printEmail(ctx, id, 'credit-request');
};
diff --git a/modules/client/back/methods/client/creditRequestPdf.js b/modules/client/back/methods/client/creditRequestPdf.js
index 2e3dc0619..a4f4ed128 100644
--- a/modules/client/back/methods/client/creditRequestPdf.js
+++ b/modules/client/back/methods/client/creditRequestPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('creditRequestPdf', {
description: 'Returns the credit request pdf',
@@ -40,17 +38,5 @@ module.exports = Self => {
}
});
- Self.creditRequestPdf = async(ctx, id) => {
- 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"`];
- };
+ Self.creditRequestPdf = (ctx, id) => Self.printReport(ctx, id, 'credit-request');
};
diff --git a/modules/client/back/methods/client/extendedListFilter.js b/modules/client/back/methods/client/extendedListFilter.js
index 8e02cd413..27bbe2a35 100644
--- a/modules/client/back/methods/client/extendedListFilter.js
+++ b/modules/client/back/methods/client/extendedListFilter.js
@@ -97,7 +97,7 @@ module.exports = Self => {
const stmts = [];
const stmt = new ParameterizedSQL(
- `SELECT
+ `SELECT
c.id,
c.name,
c.socialName,
diff --git a/modules/client/back/methods/client/getCard.js b/modules/client/back/methods/client/getCard.js
index 99c59f757..a2365ee25 100644
--- a/modules/client/back/methods/client/getCard.js
+++ b/modules/client/back/methods/client/getCard.js
@@ -80,7 +80,7 @@ module.exports = function(Self) {
const data = await Self.rawSql(query, [id, date], myOptions);
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;
};
diff --git a/modules/client/back/methods/client/incotermsAuthorizationEmail.js b/modules/client/back/methods/client/incotermsAuthorizationEmail.js
index 2a4fe593a..4a21f20b0 100644
--- a/modules/client/back/methods/client/incotermsAuthorizationEmail.js
+++ b/modules/client/back/methods/client/incotermsAuthorizationEmail.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('incotermsAuthorizationEmail', {
description: 'Sends the incoterms authorization email with an attached PDF',
@@ -47,19 +45,5 @@ module.exports = Self => {
}
});
- Self.incotermsAuthorizationEmail = async ctx => {
- 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();
- };
+ Self.incotermsAuthorizationEmail = ctx => Self.sendTemplate(ctx, 'incoterms-authorization');
};
diff --git a/modules/client/back/methods/client/incotermsAuthorizationHtml.js b/modules/client/back/methods/client/incotermsAuthorizationHtml.js
index 875495d93..0a6bba0a8 100644
--- a/modules/client/back/methods/client/incotermsAuthorizationHtml.js
+++ b/modules/client/back/methods/client/incotermsAuthorizationHtml.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('incotermsAuthorizationHtml', {
description: 'Returns the incoterms authorization email preview',
@@ -46,21 +44,5 @@ module.exports = Self => {
}
});
- Self.incotermsAuthorizationHtml = async(ctx, id) => {
- 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"`];
- };
+ Self.incotermsAuthorizationHtml = (ctx, id) => Self.printEmail(ctx, id, 'incoterms-authorization');
};
diff --git a/modules/client/back/methods/client/incotermsAuthorizationPdf.js b/modules/client/back/methods/client/incotermsAuthorizationPdf.js
index 9a8a8d296..d37e473f1 100644
--- a/modules/client/back/methods/client/incotermsAuthorizationPdf.js
+++ b/modules/client/back/methods/client/incotermsAuthorizationPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('incotermsAuthorizationPdf', {
description: 'Returns the incoterms authorization pdf',
@@ -46,17 +44,5 @@ module.exports = Self => {
}
});
- Self.incotermsAuthorizationPdf = async(ctx, id) => {
- 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"`];
- };
+ Self.incotermsAuthorizationPdf = (ctx, id) => Self.printReport(ctx, id, 'incoterms-authorization');
};
diff --git a/modules/client/back/methods/client/letterDebtorNdEmail.js b/modules/client/back/methods/client/letterDebtorNdEmail.js
index e188c6e0a..396acdb97 100644
--- a/modules/client/back/methods/client/letterDebtorNdEmail.js
+++ b/modules/client/back/methods/client/letterDebtorNdEmail.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('letterDebtorNdEmail', {
description: 'Sends the second debtor letter email with an attached PDF',
@@ -47,19 +45,5 @@ module.exports = Self => {
}
});
- Self.letterDebtorNdEmail = async ctx => {
- 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();
- };
+ Self.letterDebtorNdEmail = ctx => Self.sendTemplate(ctx, 'letter-debtor-nd');
};
diff --git a/modules/client/back/methods/client/letterDebtorNdHtml.js b/modules/client/back/methods/client/letterDebtorNdHtml.js
index 320fbaef3..f14f96dea 100644
--- a/modules/client/back/methods/client/letterDebtorNdHtml.js
+++ b/modules/client/back/methods/client/letterDebtorNdHtml.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('letterDebtorNdHtml', {
description: 'Returns the second letter debtor email preview',
@@ -46,21 +44,5 @@ module.exports = Self => {
}
});
- Self.letterDebtorNdHtml = async(ctx, id) => {
- 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"`];
- };
+ Self.letterDebtorNdHtml = (ctx, id) => Self.printEmail(ctx, id, 'letter-debtor-nd');
};
diff --git a/modules/client/back/methods/client/letterDebtorPdf.js b/modules/client/back/methods/client/letterDebtorPdf.js
index 421d531e6..943869143 100644
--- a/modules/client/back/methods/client/letterDebtorPdf.js
+++ b/modules/client/back/methods/client/letterDebtorPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('letterDebtorPdf', {
description: 'Returns the letter debtor pdf',
@@ -46,17 +44,5 @@ module.exports = Self => {
}
});
- Self.letterDebtorPdf = async(ctx, id) => {
- 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"`];
- };
+ Self.letterDebtorPdf = (ctx, id) => Self.printReport(ctx, id, 'letter-debtor');
};
diff --git a/modules/client/back/methods/client/letterDebtorStEmail.js b/modules/client/back/methods/client/letterDebtorStEmail.js
index ee39a101b..c76204fbc 100644
--- a/modules/client/back/methods/client/letterDebtorStEmail.js
+++ b/modules/client/back/methods/client/letterDebtorStEmail.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('letterDebtorStEmail', {
description: 'Sends the printer setup email with an attached PDF',
@@ -47,19 +45,5 @@ module.exports = Self => {
}
});
- Self.letterDebtorStEmail = async ctx => {
- 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();
- };
+ Self.letterDebtorStEmail = ctx => Self.sendTemplate(ctx, 'letter-debtor-st');
};
diff --git a/modules/client/back/methods/client/letterDebtorStHtml.js b/modules/client/back/methods/client/letterDebtorStHtml.js
index acf75272b..a1dcf00d7 100644
--- a/modules/client/back/methods/client/letterDebtorStHtml.js
+++ b/modules/client/back/methods/client/letterDebtorStHtml.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('letterDebtorStHtml', {
description: 'Returns the letter debtor email preview',
@@ -46,21 +44,5 @@ module.exports = Self => {
}
});
- Self.letterDebtorStHtml = async(ctx, id) => {
- 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"`];
- };
+ Self.letterDebtorStHtml = (ctx, id) => Self.printEmail(ctx, id, 'letter-debtor-st');
};
diff --git a/modules/client/back/methods/client/printerSetupEmail.js b/modules/client/back/methods/client/printerSetupEmail.js
index 254948659..2a0903e90 100644
--- a/modules/client/back/methods/client/printerSetupEmail.js
+++ b/modules/client/back/methods/client/printerSetupEmail.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('printerSetupEmail', {
description: 'Sends the printer setup email with an attached PDF',
@@ -41,19 +39,5 @@ module.exports = Self => {
}
});
- Self.printerSetupEmail = async ctx => {
- 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();
- };
+ Self.printerSetupEmail = ctx => Self.sendTemplate(ctx, 'printer-setup');
};
diff --git a/modules/client/back/methods/client/printerSetupHtml.js b/modules/client/back/methods/client/printerSetupHtml.js
index 1ef1843e0..c9d94d1c2 100644
--- a/modules/client/back/methods/client/printerSetupHtml.js
+++ b/modules/client/back/methods/client/printerSetupHtml.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('printerSetupHtml', {
description: 'Returns the printer setup email preview',
@@ -40,19 +38,5 @@ module.exports = Self => {
}
});
- Self.printerSetupHtml = async(ctx, id) => {
- 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"`];
- };
+ Self.printerSetupHtml = (ctx, id) => Self.printEmail(ctx, id, 'printer-setup');
};
diff --git a/modules/client/back/methods/client/sepaCoreEmail.js b/modules/client/back/methods/client/sepaCoreEmail.js
index 93c9d4302..20931eb03 100644
--- a/modules/client/back/methods/client/sepaCoreEmail.js
+++ b/modules/client/back/methods/client/sepaCoreEmail.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('sepaCoreEmail', {
description: 'Sends the campaign metrics email with an attached PDF',
@@ -47,19 +45,5 @@ module.exports = Self => {
}
});
- Self.sepaCoreEmail = async ctx => {
- 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();
- };
+ Self.sepaCoreEmail = ctx => Self.sendTemplate(ctx, 'sepa-core');
};
diff --git a/modules/client/back/methods/receipt/balanceCompensationPdf.js b/modules/client/back/methods/receipt/balanceCompensationPdf.js
index ff8713253..e790d54a1 100644
--- a/modules/client/back/methods/receipt/balanceCompensationPdf.js
+++ b/modules/client/back/methods/receipt/balanceCompensationPdf.js
@@ -1,5 +1,3 @@
-const { Report } = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('balanceCompensationPdf', {
description: 'Returns the the debit balances compensation pdf',
@@ -10,7 +8,7 @@ module.exports = Self => {
type: 'number',
required: true,
description: 'The receipt id',
- http: { source: 'path' }
+ http: {source: 'path'}
}
],
returns: [
@@ -34,17 +32,5 @@ module.exports = Self => {
}
});
- Self.balanceCompensationPdf = async(ctx, id) => {
- 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"`];
- };
+ Self.balanceCompensationPdf = (ctx, id) => Self.printReport(ctx, id, 'balance-compensation');
};
diff --git a/modules/client/back/methods/receipt/receiptPdf.js b/modules/client/back/methods/receipt/receiptPdf.js
index f55e05040..433f386db 100644
--- a/modules/client/back/methods/receipt/receiptPdf.js
+++ b/modules/client/back/methods/receipt/receiptPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('receiptPdf', {
description: 'Returns the receipt pdf',
@@ -39,17 +37,5 @@ module.exports = Self => {
}
});
- Self.receiptPdf = async(ctx, id) => {
- 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"`];
- };
+ Self.receiptPdf = (ctx, id) => Self.printReport(ctx, id, 'receipt');
};
diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js
index 2d8e7bd27..c41085b79 100644
--- a/modules/client/back/models/client.js
+++ b/modules/client/back/models/client.js
@@ -279,6 +279,18 @@ module.exports = Self => {
// Credit changes
if (changes.credit !== undefined)
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 => {
diff --git a/modules/client/back/models/receipt.json b/modules/client/back/models/receipt.json
index 19107f561..da7879df9 100644
--- a/modules/client/back/models/receipt.json
+++ b/modules/client/back/models/receipt.json
@@ -62,6 +62,11 @@
"type": "belongsTo",
"model": "Bank",
"foreignKey": "bankFk"
+ },
+ "supplier": {
+ "type": "belongsTo",
+ "model": "Supplier",
+ "foreignKey": "companyFk"
}
}
-}
\ No newline at end of file
+}
diff --git a/modules/client/front/descriptor/index.html b/modules/client/front/descriptor/index.html
index edf3cc8c3..5aaecbdb0 100644
--- a/modules/client/front/descriptor/index.html
+++ b/modules/client/front/descriptor/index.html
@@ -70,11 +70,12 @@
icon="icon-no036"
ng-if="$ctrl.client.isTaxDataChecked == false">
-
-
+
diff --git a/modules/client/front/descriptor/index.js b/modules/client/front/descriptor/index.js
index 86e8f4e61..cdabf13e7 100644
--- a/modules/client/front/descriptor/index.js
+++ b/modules/client/front/descriptor/index.js
@@ -46,8 +46,9 @@ class Controller extends Descriptor {
}
clientUnpaid() {
- return this.$t(`Unpaid Dated`, {dated: this.client.unpaid.dated}) +
- '
' + this.$t(`Unpaid Amount`, {amount: this.client.unpaid.amount});
+ return this.$t(`Unpaid`) + '
'
+ + this.$t(`Unpaid Dated`, {dated: this.client.unpaid.dated}) + '
'
+ + this.$t(`Unpaid Amount`, {amount: this.client.unpaid.amount});
}
}
diff --git a/modules/client/front/unpaid/index.html b/modules/client/front/unpaid/index.html
index 5f6edfe10..2a0432f5a 100644
--- a/modules/client/front/unpaid/index.html
+++ b/modules/client/front/unpaid/index.html
@@ -9,12 +9,12 @@
-
\ No newline at end of file
+
diff --git a/modules/client/front/unpaid/index.js b/modules/client/front/unpaid/index.js
index fcf620b54..1585b808d 100644
--- a/modules/client/front/unpaid/index.js
+++ b/modules/client/front/unpaid/index.js
@@ -6,9 +6,17 @@ export default class Controller extends Section {
if (hasData && !this.clientUnpaid.dated)
this.clientUnpaid.dated = Date.vnNew();
}
+
+ onSubmit() {
+ this.$.watcher.submit()
+ .then(() => this.card.reload());
+ }
}
ngModule.vnComponent('vnClientUnpaid', {
template: require('./index.html'),
- controller: Controller
+ controller: Controller,
+ require: {
+ card: '^vnClientCard'
+ }
});
diff --git a/modules/entry/back/methods/entry/entryOrderPdf.js b/modules/entry/back/methods/entry/entryOrderPdf.js
index e6d37fdb6..f77832162 100644
--- a/modules/entry/back/methods/entry/entryOrderPdf.js
+++ b/modules/entry/back/methods/entry/entryOrderPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('entryOrderPdf', {
description: 'Returns the entry order pdf',
@@ -38,17 +36,5 @@ module.exports = Self => {
}
});
- Self.entryOrderPdf = async(ctx, id) => {
- 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"`];
- };
+ Self.entryOrderPdf = (ctx, id) => Self.printReport(ctx, id, 'entry-order');
};
diff --git a/modules/invoiceIn/back/methods/invoice-in/invoiceInEmail.js b/modules/invoiceIn/back/methods/invoice-in/invoiceInEmail.js
index 0768541a8..a0af3da69 100644
--- a/modules/invoiceIn/back/methods/invoice-in/invoiceInEmail.js
+++ b/modules/invoiceIn/back/methods/invoice-in/invoiceInEmail.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('invoiceInEmail', {
description: 'Sends the invoice in email with an attached PDF',
@@ -35,19 +33,5 @@ module.exports = Self => {
}
});
- Self.invoiceInEmail = async ctx => {
- 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();
- };
+ Self.invoiceInEmail = ctx => Self.sendTemplate(ctx, 'invoiceIn');
};
diff --git a/modules/invoiceIn/back/methods/invoice-in/invoiceInPdf.js b/modules/invoiceIn/back/methods/invoice-in/invoiceInPdf.js
index e7962c93f..681a19fc6 100644
--- a/modules/invoiceIn/back/methods/invoice-in/invoiceInPdf.js
+++ b/modules/invoiceIn/back/methods/invoice-in/invoiceInPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('invoiceInPdf', {
description: 'Returns the invoiceIn pdf',
@@ -34,17 +32,5 @@ module.exports = Self => {
}
});
- Self.invoiceInPdf = async(ctx, id) => {
- 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"`];
- };
+ Self.invoiceInPdf = (ctx, id) => Self.printReport(ctx, id, 'invoiceIn');
};
diff --git a/modules/invoiceOut/back/methods/invoiceOut/exportationPdf.js b/modules/invoiceOut/back/methods/invoiceOut/exportationPdf.js
index e947c5144..7a2526b35 100644
--- a/modules/invoiceOut/back/methods/invoiceOut/exportationPdf.js
+++ b/modules/invoiceOut/back/methods/invoiceOut/exportationPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('exportationPdf', {
description: 'Returns the exportation pdf',
@@ -39,17 +37,5 @@ module.exports = Self => {
}
});
- Self.exportationPdf = async(ctx, reference) => {
- 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('exportation', params);
- const stream = await report.toPdfStream();
-
- return [stream, 'application/pdf', `filename="doc-${reference}.pdf"`];
- };
+ Self.exportationPdf = (ctx, reference) => Self.printReport(ctx, reference, 'exportation');
};
diff --git a/modules/item/back/methods/item-image-queue/download.js b/modules/item/back/methods/item-image-queue/download.js
new file mode 100644
index 000000000..cdc0fe049
--- /dev/null
+++ b/modules/item/back/methods/item-image-queue/download.js
@@ -0,0 +1,191 @@
+const axios = require('axios');
+const uuid = require('uuid');
+const fs = require('fs/promises');
+const { createWriteStream } = require('fs');
+const path = require('path');
+const gm = require('gm');
+
+module.exports = Self => {
+ Self.remoteMethod('download', {
+ description: 'Processes the image download queue',
+ accessType: 'WRITE',
+ http: {
+ path: `/download`,
+ verb: 'POST',
+ },
+ });
+
+ Self.download = async () => {
+ const models = Self.app.models;
+ const tempContainer = await models.TempContainer.container(
+ 'salix-image'
+ );
+ const tempPath = path.join(
+ tempContainer.client.root,
+ tempContainer.name
+ );
+ const maxAttempts = 3;
+ const collectionName = 'catalog';
+
+ const tx = await Self.beginTransaction({});
+
+ let tempFilePath;
+ let queueRow;
+ try {
+ const myOptions = { transaction: tx };
+
+ queueRow = await Self.findOne(
+ {
+ fields: ['id', 'itemFk', 'url', 'attempts'],
+ where: {
+ url: { neq: null },
+ attempts: {
+ lt: maxAttempts,
+ },
+ },
+ order: 'priority, attempts, updated',
+ },
+ myOptions
+ );
+
+ if (!queueRow) return;
+
+ const collection = await models.ImageCollection.findOne(
+ {
+ fields: [
+ 'id',
+ 'maxWidth',
+ 'maxHeight',
+ 'model',
+ 'property',
+ ],
+ where: { name: collectionName },
+ include: {
+ relation: 'sizes',
+ scope: {
+ fields: ['width', 'height', 'crop'],
+ },
+ },
+ },
+ myOptions
+ );
+
+ const fileName = `${uuid.v4()}.png`;
+ tempFilePath = path.join(tempPath, fileName);
+
+ // Insert image row
+ await models.Image.create(
+ {
+ name: fileName,
+ collectionFk: collectionName,
+ updated: Date.vnNow(),
+ },
+ myOptions
+ );
+
+ // Update item
+ const model = models[collection.model];
+ if (!model) throw new Error('No matching model found');
+
+ const item = await model.findById(queueRow.itemFk, null, myOptions);
+ if (item) {
+ await item.updateAttribute(
+ collection.property,
+ fileName,
+ myOptions
+ );
+ }
+
+ // Download remote image
+ const response = await axios.get(queueRow.url, {
+ responseType: 'stream',
+ });
+
+ const writeStream = createWriteStream(tempFilePath);
+ await new Promise((resolve, reject) => {
+ writeStream.on('open', () => response.data.pipe(writeStream));
+ writeStream.on('finish', () => resolve());
+ writeStream.on('error', error => reject(error));
+ });
+
+ // Resize
+ const container = await models.ImageContainer.container(
+ collectionName
+ );
+ const rootPath = container.client.root;
+ const collectionDir = path.join(rootPath, collectionName);
+
+ // To max size
+ const { maxWidth, maxHeight } = collection;
+ const fullSizePath = path.join(collectionDir, 'full');
+ const toFullSizePath = `${fullSizePath}/${fileName}`;
+
+ await fs.mkdir(fullSizePath, { recursive: true });
+ await new Promise((resolve, reject) => {
+ gm(tempFilePath)
+ .resize(maxWidth, maxHeight, '>')
+ .setFormat('png')
+ .write(toFullSizePath, function (err) {
+ if (err) reject(err);
+ if (!err) resolve();
+ });
+ });
+
+ // To collection sizes
+ for (const size of collection.sizes()) {
+ const { width, height } = size;
+
+ const sizePath = path.join(collectionDir, `${width}x${height}`);
+ const toSizePath = `${sizePath}/${fileName}`;
+
+ await fs.mkdir(sizePath, { recursive: true });
+ await new Promise((resolve, reject) => {
+ const gmInstance = gm(tempFilePath);
+
+ if (size.crop) {
+ gmInstance
+ .resize(width, height, '^')
+ .gravity('Center')
+ .crop(width, height);
+ }
+
+ if (!size.crop) gmInstance.resize(width, height, '>');
+
+ gmInstance
+ .setFormat('png')
+ .write(toSizePath, function (err) {
+ if (err) reject(err);
+ if (!err) resolve();
+ });
+ });
+ }
+
+ try {
+ await fs.unlink(tempFilePath);
+ } catch (error) { }
+
+ await queueRow.destroy(myOptions);
+
+ // Restart queue
+ Self.download();
+
+ await tx.commit();
+ } catch (error) {
+ await tx.rollback();
+
+ if (queueRow.attempts < maxAttempts) {
+ await queueRow.updateAttributes({
+ error: error,
+ attempts: queueRow.attempts + 1,
+ updated: Date.vnNew(),
+ });
+ }
+
+ try {
+ await fs.unlink(tempFilePath);
+ } catch (error) { }
+
+ Self.download();
+ }
+ };
+};
diff --git a/modules/item/back/methods/item-image-queue/downloadImages.js b/modules/item/back/methods/item-image-queue/downloadImages.js
index c4d7f4b98..7f53df95a 100644
--- a/modules/item/back/methods/item-image-queue/downloadImages.js
+++ b/modules/item/back/methods/item-image-queue/downloadImages.js
@@ -62,7 +62,7 @@ module.exports = Self => {
writeStream.on('open', () => response.pipe(writeStream));
writeStream.on('error', async error =>
await errorHandler(image.itemFk, error, filePath));
- writeStream.on('finish', writeStream.end());
+ writeStream.on('finish', () => writeStream.end());
writeStream.on('close', async function() {
try {
diff --git a/modules/item/back/methods/item/labelPdf.js b/modules/item/back/methods/item/labelPdf.js
index 747869b37..c2462353d 100644
--- a/modules/item/back/methods/item/labelPdf.js
+++ b/modules/item/back/methods/item/labelPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('labelPdf', {
description: 'Returns the item label pdf',
@@ -56,17 +54,5 @@ module.exports = Self => {
}
});
- Self.labelPdf = async(ctx, id) => {
- 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('item-label', params);
- const stream = await report.toPdfStream();
-
- return [stream, 'application/pdf', `filename="item-${id}.pdf"`];
- };
+ Self.labelPdf = (ctx, id) => Self.printReport(ctx, id, 'item-label');
};
diff --git a/modules/item/back/models/item-image-queue.js b/modules/item/back/models/item-image-queue.js
index e2059ddac..35a467693 100644
--- a/modules/item/back/models/item-image-queue.js
+++ b/modules/item/back/models/item-image-queue.js
@@ -1,3 +1,3 @@
module.exports = Self => {
- require('../methods/item-image-queue/downloadImages')(Self);
+ require('../methods/item-image-queue/download')(Self);
};
diff --git a/modules/route/back/methods/route/driverRouteEmail.js b/modules/route/back/methods/route/driverRouteEmail.js
index 4d5279d2d..82b005e44 100644
--- a/modules/route/back/methods/route/driverRouteEmail.js
+++ b/modules/route/back/methods/route/driverRouteEmail.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('driverRouteEmail', {
description: 'Sends the driver route email with an attached PDF',
@@ -41,19 +39,5 @@ module.exports = Self => {
}
});
- Self.driverRouteEmail = async ctx => {
- 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('driver-route', params);
-
- return email.send();
- };
+ Self.driverRouteEmail = ctx => Self.sendTemplate(ctx, 'driver-route');
};
diff --git a/modules/route/back/methods/route/driverRoutePdf.js b/modules/route/back/methods/route/driverRoutePdf.js
index 65748afad..f0cd75f0e 100644
--- a/modules/route/back/methods/route/driverRoutePdf.js
+++ b/modules/route/back/methods/route/driverRoutePdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('driverRoutePdf', {
description: 'Returns the driver route pdf',
@@ -39,17 +37,5 @@ module.exports = Self => {
}
});
- Self.driverRoutePdf = async(ctx, id) => {
- 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('driver-route', params);
- const stream = await report.toPdfStream();
-
- return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
- };
+ Self.driverRoutePdf = (ctx, id) => Self.printReport(ctx, id, 'driver-route');
};
diff --git a/modules/supplier/back/methods/supplier/campaignMetricsPdf.js b/modules/supplier/back/methods/supplier/campaignMetricsPdf.js
index 7bd65ffcb..f7ff900e7 100644
--- a/modules/supplier/back/methods/supplier/campaignMetricsPdf.js
+++ b/modules/supplier/back/methods/supplier/campaignMetricsPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('campaignMetricsPdf', {
description: 'Returns the campaign metrics pdf',
@@ -49,17 +47,5 @@ module.exports = Self => {
}
});
- Self.campaignMetricsPdf = async(ctx, id) => {
- 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('supplier-campaign-metrics', params);
- const stream = await report.toPdfStream();
-
- return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
- };
+ Self.campaignMetricsPdf = (ctx, id) => Self.printReport(ctx, id, 'supplier-campaign-metrics');
};
diff --git a/modules/ticket/back/methods/ticket/collectionLabel.js b/modules/ticket/back/methods/ticket/collectionLabel.js
index 7601961fb..74b5b2c0a 100644
--- a/modules/ticket/back/methods/ticket/collectionLabel.js
+++ b/modules/ticket/back/methods/ticket/collectionLabel.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('collectionLabel', {
description: 'Returns the collection label',
@@ -39,17 +37,5 @@ module.exports = Self => {
}
});
- Self.collectionLabel = async(ctx, id) => {
- 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('collection-label', params);
- const stream = await report.toPdfStream();
-
- return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
- };
+ Self.collectionLabel = (ctx, id) => Self.printReport(ctx, id, 'collection-label');
};
diff --git a/modules/ticket/back/methods/ticket/componentUpdate.js b/modules/ticket/back/methods/ticket/componentUpdate.js
index 94b91e237..c23d1669e 100644
--- a/modules/ticket/back/methods/ticket/componentUpdate.js
+++ b/modules/ticket/back/methods/ticket/componentUpdate.js
@@ -165,18 +165,29 @@ module.exports = Self => {
'shipped',
'landed',
'isDeleted',
- 'routeFk'
+ 'routeFk',
+ 'nickname'
],
include: [
{
relation: 'client',
scope: {
fields: 'salesPersonFk'
- }
- }]
+ },
+ include: [
+ {
+ relation: 'address',
+ scope: {
+ fields: 'nickname'
+ }
+ }
+ ]
+ },
+ ]
}, myOptions);
args.routeFk = null;
+ if (args.isWithoutNegatives === false) delete args.isWithoutNegatives;
const updatedTicket = Object.assign({}, args);
delete updatedTicket.ctx;
delete updatedTicket.option;
@@ -224,37 +235,41 @@ module.exports = Self => {
}
const changes = loggable.getChanges(originalTicket, updatedTicket);
- const oldProperties = await loggable.translateValues(Self, changes.old);
- const newProperties = await loggable.translateValues(Self, changes.new);
+ const hasChanges = Object.keys(changes.old).length > 0 || Object.keys(changes.new).length > 0;
- await models.TicketLog.create({
- originFk: args.id,
- userFk: userId,
- action: 'update',
- changedModel: 'Ticket',
- changedModelId: args.id,
- oldInstance: oldProperties,
- newInstance: newProperties
- }, myOptions);
+ if (hasChanges) {
+ const oldProperties = await loggable.translateValues(Self, changes.old);
+ const newProperties = await loggable.translateValues(Self, changes.new);
- const salesPersonId = originalTicket.client().salesPersonFk;
- if (salesPersonId) {
- const origin = ctx.req.headers.origin;
+ await models.TicketLog.create({
+ originFk: args.id,
+ userFk: userId,
+ action: 'update',
+ changedModel: 'Ticket',
+ changedModelId: args.id,
+ oldInstance: oldProperties,
+ newInstance: newProperties
+ }, myOptions);
- let changesMade = '';
- for (let change in newProperties) {
- let value = newProperties[change];
- let oldValue = oldProperties[change];
+ const salesPersonId = originalTicket.client().salesPersonFk;
+ if (salesPersonId) {
+ const origin = ctx.req.headers.origin;
- changesMade += `\r\n~${$t(change)}: ${oldValue}~ ➔ *${$t(change)}: ${value}*`;
+ let changesMade = '';
+ for (let change in newProperties) {
+ let value = newProperties[change];
+ let oldValue = oldProperties[change];
+
+ changesMade += `\r\n~${$t(change)}: ${oldValue}~ ➔ *${$t(change)}: ${value}*`;
+ }
+
+ const message = $t('Changed this data from the ticket', {
+ ticketId: args.id,
+ ticketUrl: `${origin}/#!/ticket/${args.id}/sale`,
+ changes: changesMade
+ });
+ await models.Chat.sendCheckingPresence(ctx, salesPersonId, message);
}
-
- const message = $t('Changed this data from the ticket', {
- ticketId: args.id,
- ticketUrl: `${origin}/#!/ticket/${args.id}/sale`,
- changes: changesMade
- });
- await models.Chat.sendCheckingPresence(ctx, salesPersonId, message);
}
res.id = args.id;
diff --git a/modules/ticket/back/methods/ticket/deliveryNoteEmail.js b/modules/ticket/back/methods/ticket/deliveryNoteEmail.js
index cf9f5dd62..4b275b45e 100644
--- a/modules/ticket/back/methods/ticket/deliveryNoteEmail.js
+++ b/modules/ticket/back/methods/ticket/deliveryNoteEmail.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('deliveryNoteEmail', {
description: 'Sends the delivery note email with an attached PDF',
@@ -47,19 +45,5 @@ module.exports = Self => {
}
});
- Self.deliveryNoteEmail = async ctx => {
- 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('delivery-note', params);
-
- return email.send();
- };
+ Self.deliveryNoteEmail = ctx => Self.sendTemplate(ctx, 'delivery-note');
};
diff --git a/modules/ticket/back/methods/ticket/deliveryNotePdf.js b/modules/ticket/back/methods/ticket/deliveryNotePdf.js
index b2b3f7198..628e16bcd 100644
--- a/modules/ticket/back/methods/ticket/deliveryNotePdf.js
+++ b/modules/ticket/back/methods/ticket/deliveryNotePdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('deliveryNotePdf', {
description: 'Returns the delivery note pdf',
@@ -46,17 +44,5 @@ module.exports = Self => {
}
});
- Self.deliveryNotePdf = async(ctx, id) => {
- 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('delivery-note', params);
- const stream = await report.toPdfStream();
-
- return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
- };
+ Self.deliveryNotePdf = (ctx, id) => Self.printReport(ctx, id, 'delivery-note');
};
diff --git a/modules/ticket/back/methods/ticket/expeditionPalletLabel.js b/modules/ticket/back/methods/ticket/expeditionPalletLabel.js
index 2215263dd..9830364d6 100644
--- a/modules/ticket/back/methods/ticket/expeditionPalletLabel.js
+++ b/modules/ticket/back/methods/ticket/expeditionPalletLabel.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('expeditionPalletLabel', {
description: 'Returns the expedition pallet label',
@@ -39,17 +37,5 @@ module.exports = Self => {
}
});
- Self.expeditionPalletLabel = async(ctx, id) => {
- 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('expedition-pallet-label', params);
- const stream = await report.toPdfStream();
-
- return [stream, 'application/pdf', `filename="doc-${id}.pdf"`];
- };
+ Self.expeditionPalletLabel = (ctx, id) => Self.printReport(ctx, id, 'expedition-pallet-label');
};
diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js
new file mode 100644
index 000000000..ab1c32d1b
--- /dev/null
+++ b/modules/ticket/back/methods/ticket/saveSign.js
@@ -0,0 +1,132 @@
+const UserError = require('vn-loopback/util/user-error');
+
+module.exports = Self => {
+ Self.remoteMethodCtx('saveSign', {
+ description: 'Save sign',
+ accessType: 'WRITE',
+ accepts:
+ [
+ {
+ arg: 'tickets',
+ type: ['number'],
+ required: true,
+ description: 'The tickets'
+ },
+ {
+ arg: 'location',
+ type: 'object',
+ description: 'The employee location the moment the sign is saved'
+ },
+ {
+ arg: 'signedTime',
+ type: 'date',
+ description: 'The signed time'
+ }
+ ],
+ http: {
+ path: `/saveSign`,
+ verb: 'POST'
+ }
+ });
+
+ Self.saveSign = async(ctx, options) => {
+ const args = Object.assign({}, ctx.args);
+ const models = Self.app.models;
+ const myOptions = {};
+ let tx;
+
+ if (typeof options == 'object')
+ Object.assign(myOptions, options);
+
+ if (!myOptions.transaction) {
+ tx = await Self.beginTransaction({});
+ myOptions.transaction = tx;
+ }
+
+ async function setLocation(ticketId) {
+ await models.Delivery.create({
+ ticketFk: ticketId,
+ longitude: args.location.Longitude,
+ latitude: args.location.Latitude,
+ dated: args.signedTime || new Date()
+ }, myOptions);
+ }
+
+ async function gestDocExists(ticketId) {
+ const ticketDms = await models.TicketDms.findOne({
+ where: {ticketFk: ticketId},
+ fields: ['dmsFk']
+ }, myOptions);
+
+ if (!ticketDms) return false;
+
+ const ticket = await models.Ticket.findById(ticketId, {fields: ['isSigned']}, myOptions);
+ if (ticket.isSigned == true)
+ return true;
+ else
+ await models.Dms.destroyAll({where: {reference: ticketId}}, myOptions);
+
+ return false;
+ }
+
+ async function createGestDoc(id) {
+ const ticket = await models.Ticket.findById(id,
+ {include: [
+ {
+ relation: 'warehouse',
+ scope: {
+ fields: ['id']
+ }
+ }, {
+ relation: 'client',
+ scope: {
+ fields: ['name']
+ }
+ }, {
+ relation: 'route',
+ scope: {
+ fields: ['id']
+ }
+ }
+ ]
+ }, myOptions);
+ const dmsType = await models.DmsType.findOne({where: {code: 'Ticket'}, fields: ['id']}, myOptions);
+ const ctxUploadFile = Object.assign({}, ctx);
+ ctxUploadFile.args = {
+ warehouseId: ticket.warehouseFk,
+ companyId: ticket.companyFk,
+ dmsTypeId: dmsType.id,
+ reference: id,
+ description: `Ticket ${id} Cliente ${ticket.client().name} Ruta ${ticket.route().id}`,
+ hasFile: true
+ };
+ await models.Ticket.uploadFile(ctxUploadFile, id, myOptions);
+ }
+
+ try {
+ for (let i = 0; i < args.tickets.length; i++) {
+ const ticketState = await models.TicketState.findOne(
+ {where: {ticketFk: args.tickets[i]},
+ fields: ['alertLevel']
+ }, myOptions);
+
+ const packedAlertLevel = await models.AlertLevel.findOne({where: {code: 'PACKED'},
+ fields: ['id']
+ }, myOptions);
+
+ if (ticketState.alertLevel < packedAlertLevel.id)
+ throw new UserError('This ticket cannot be signed because it has not been boxed');
+ else if (!await gestDocExists(args.tickets[i])) {
+ if (args.location) setLocation(args.tickets[i]);
+ await createGestDoc(args.tickets[i]);
+ await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [args.tickets[i], 'DELIVERED'], myOptions);
+ }
+ }
+
+ if (tx) await tx.commit();
+ } catch (e) {
+ if (tx) await tx.rollback();
+ throw e;
+ }
+ };
+};
diff --git a/modules/ticket/back/methods/ticket/specs/merge.spec.js b/modules/ticket/back/methods/ticket/specs/merge.spec.js
index 6b533e47c..78eb0c8f3 100644
--- a/modules/ticket/back/methods/ticket/specs/merge.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/merge.spec.js
@@ -2,13 +2,13 @@ const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
describe('ticket merge()', () => {
- const tickets = [{
+ const tickets = {
originId: 13,
destinationId: 12,
originShipped: Date.vnNew(),
destinationShipped: Date.vnNew(),
workerFk: 1
- }];
+ };
const activeCtx = {
accessToken: {userId: 9},
@@ -37,14 +37,14 @@ describe('ticket merge()', () => {
const options = {transaction: tx};
const chatNotificationBeforeMerge = await models.Chat.find();
- await models.Ticket.merge(ctx, tickets, options);
+ await models.Ticket.merge(ctx, [tickets], options);
- const createdTicketLog = await models.TicketLog.find({where: {originFk: tickets[0].originId}}, options);
- const deletedTicket = await models.Ticket.findOne({where: {id: tickets[0].originId}}, options);
- const salesTicketFuture = await models.Sale.find({where: {ticketFk: tickets[0].destinationId}}, options);
+ const createdTicketLog = await models.TicketLog.find({where: {originFk: tickets.originId}}, options);
+ const deletedTicket = await models.Ticket.findOne({where: {id: tickets.originId}}, options);
+ const salesTicketFuture = await models.Sale.find({where: {ticketFk: tickets.destinationId}}, options);
const chatNotificationAfterMerge = await models.Chat.find();
- expect(createdTicketLog.length).toEqual(1);
+ expect(createdTicketLog.length).toEqual(2);
expect(deletedTicket.isDeleted).toEqual(true);
expect(salesTicketFuture.length).toEqual(2);
expect(chatNotificationBeforeMerge.length).toEqual(chatNotificationAfterMerge.length - 2);
diff --git a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js
new file mode 100644
index 000000000..6b532a5d1
--- /dev/null
+++ b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js
@@ -0,0 +1,32 @@
+const models = require('vn-loopback/server/server').models;
+
+describe('Ticket saveSign()', () => {
+ const FormData = require('form-data');
+ const data = new FormData();
+ let ctx = {req: {
+ accessToken: {userId: 9},
+ headers: {
+ ...data.getHeaders()
+ }
+
+ }};
+
+ it(`should throw error if the ticket's alert level is lower than 2`, async() => {
+ const tx = await models.TicketDms.beginTransaction({});
+ const ticketWithOkState = 12;
+ let error;
+ try {
+ const options = {transaction: tx};
+ ctx.args = {tickets: [ticketWithOkState]};
+
+ await models.Ticket.saveSign(ctx, options);
+
+ await tx.rollback();
+ } catch (e) {
+ error = e;
+ await tx.rollback();
+ }
+
+ expect(error).toBeDefined();
+ });
+});
diff --git a/modules/ticket/back/methods/ticket/transferSales.js b/modules/ticket/back/methods/ticket/transferSales.js
index 57f620f3d..48035648c 100644
--- a/modules/ticket/back/methods/ticket/transferSales.js
+++ b/modules/ticket/back/methods/ticket/transferSales.js
@@ -105,8 +105,8 @@ module.exports = Self => {
originFk: id,
userFk: userId,
action: 'update',
- changedModel: 'Ticket',
- changedModelId: id,
+ changedModel: 'Sale',
+ changedModelId: sale.id,
oldInstance: {
item: originalSaleData.itemFk,
quantity: originalSaleData.quantity,
@@ -126,8 +126,8 @@ module.exports = Self => {
originFk: ticketId,
userFk: userId,
action: 'update',
- changedModel: 'Ticket',
- changedModelId: ticketId,
+ changedModel: 'Sale',
+ changedModelId: sale.id,
oldInstance: {
item: originalSaleData.itemFk,
quantity: originalSaleData.quantity,
@@ -177,16 +177,16 @@ module.exports = Self => {
// Update original sale
const rest = originalSale.quantity - sale.quantity;
- query = `UPDATE sale
+ query = `UPDATE sale
SET quantity = ?
WHERE id = ?`;
await Self.rawSql(query, [rest, sale.id], options);
// Clone sale with new quantity
- query = `INSERT INTO sale (itemFk, ticketFk, concept, quantity, originalQuantity, price, discount, priceFixed,
+ query = `INSERT INTO sale (itemFk, ticketFk, concept, quantity, originalQuantity, price, discount, priceFixed,
reserved, isPicked, isPriceFixed, isAdded)
- SELECT itemFk, ?, concept, ?, originalQuantity, price, discount, priceFixed,
- reserved, isPicked, isPriceFixed, isAdded
+ SELECT itemFk, ?, concept, ?, originalQuantity, price, discount, priceFixed,
+ reserved, isPicked, isPriceFixed, isAdded
FROM sale
WHERE id = ?`;
await Self.rawSql(query, [ticketId, sale.quantity, sale.id], options);
diff --git a/modules/ticket/back/models/ticket-methods.js b/modules/ticket/back/models/ticket-methods.js
index 73df0579c..3992e7307 100644
--- a/modules/ticket/back/models/ticket-methods.js
+++ b/modules/ticket/back/models/ticket-methods.js
@@ -39,4 +39,5 @@ module.exports = function(Self) {
require('../methods/ticket/isRoleAdvanced')(Self);
require('../methods/ticket/collectionLabel')(Self);
require('../methods/ticket/expeditionPalletLabel')(Self);
+ require('../methods/ticket/saveSign')(Self);
};
diff --git a/modules/ticket/back/models/ticket.json b/modules/ticket/back/models/ticket.json
index 09b01d213..1cf2642a5 100644
--- a/modules/ticket/back/models/ticket.json
+++ b/modules/ticket/back/models/ticket.json
@@ -36,7 +36,7 @@
"type": "number"
},
"updated": {
- "type": "date",
+ "type": "date",
"mysql": {
"columnName": "created"
}
@@ -44,6 +44,9 @@
"isDeleted": {
"type": "boolean"
},
+ "isSigned": {
+ "type": "boolean"
+ },
"priority": {
"type": "number"
},
@@ -136,4 +139,4 @@
"foreignKey": "zoneFk"
}
}
-}
\ No newline at end of file
+}
diff --git a/modules/travel/back/methods/travel/extraCommunityEmail.js b/modules/travel/back/methods/travel/extraCommunityEmail.js
index dd93ed905..f4b09b79d 100644
--- a/modules/travel/back/methods/travel/extraCommunityEmail.js
+++ b/modules/travel/back/methods/travel/extraCommunityEmail.js
@@ -1,5 +1,3 @@
-const {Email} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('extraCommunityEmail', {
description: 'Sends the extra community email with an attached PDF',
@@ -74,19 +72,5 @@ module.exports = Self => {
}
});
- Self.extraCommunityEmail = async ctx => {
- 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('extra-community', params);
-
- return email.send();
- };
+ Self.extraCommunityEmail = ctx => Self.sendTemplate(ctx, 'extra-community');
};
diff --git a/modules/travel/back/methods/travel/extraCommunityPdf.js b/modules/travel/back/methods/travel/extraCommunityPdf.js
index a68e5cd09..676b98be2 100644
--- a/modules/travel/back/methods/travel/extraCommunityPdf.js
+++ b/modules/travel/back/methods/travel/extraCommunityPdf.js
@@ -1,5 +1,3 @@
-const {Report} = require('vn-print');
-
module.exports = Self => {
Self.remoteMethodCtx('extraCommunityPdf', {
description: 'Returns the extra community pdf',
@@ -11,6 +9,16 @@ module.exports = Self => {
description: 'The recipient id',
required: false
},
+ {
+ arg: 'filter',
+ type: 'object',
+ description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string'
+ },
+ {
+ arg: 'search',
+ type: 'string',
+ description: 'Searchs the travel by id'
+ },
{
arg: 'landedTo',
type: 'date'
@@ -73,17 +81,5 @@ module.exports = Self => {
}
});
- Self.extraCommunityPdf = async ctx => {
- 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('extra-community', params);
- const stream = await report.toPdfStream();
-
- return [stream, 'application/pdf', `filename="extra-community.pdf"`];
- };
+ Self.extraCommunityPdf = ctx => Self.printReport(ctx, null, 'extra-community');
};
diff --git a/modules/travel/front/extra-community/index.html b/modules/travel/front/extra-community/index.html
index 73e62b174..c888f97da 100644
--- a/modules/travel/front/extra-community/index.html
+++ b/modules/travel/front/extra-community/index.html
@@ -1,7 +1,7 @@
{
+ Self.remoteMethodCtx('getMailStates', {
+ description: 'Get the states of a month about time control mail',
+ accessType: 'READ',
+ accepts: [{
+ arg: 'id',
+ type: 'number',
+ description: 'The worker id',
+ http: {source: 'path'}
+ },
+ {
+ arg: 'month',
+ type: 'number',
+ description: 'The number of the month'
+ },
+ {
+ arg: 'year',
+ type: 'number',
+ description: 'The number of the year'
+ }],
+ returns: [{
+ type: ['object'],
+ root: true
+ }],
+ http: {
+ path: `/:id/getMailStates`,
+ verb: 'GET'
+ }
+ });
+
+ Self.getMailStates = async(ctx, workerId, options) => {
+ const models = Self.app.models;
+ const args = ctx.args;
+ const myOptions = {};
+
+ if (typeof options == 'object')
+ Object.assign(myOptions, options);
+
+ const times = await models.Time.find({
+ fields: ['week'],
+ where: {
+ month: args.month,
+ year: args.year
+ }
+ }, myOptions);
+
+ const weeks = times.map(time => time.week);
+ const weekNumbersSet = new Set(weeks);
+ const weekNumbers = Array.from(weekNumbersSet);
+
+ const workerTimeControlMails = await models.WorkerTimeControlMail.find({
+ where: {
+ workerFk: workerId,
+ year: args.year,
+ week: {inq: weekNumbers}
+ }
+ }, myOptions);
+
+ return workerTimeControlMails;
+ };
+};
diff --git a/modules/worker/back/methods/worker-time-control/specs/getMailStates.spec.js b/modules/worker/back/methods/worker-time-control/specs/getMailStates.spec.js
new file mode 100644
index 000000000..cbad32323
--- /dev/null
+++ b/modules/worker/back/methods/worker-time-control/specs/getMailStates.spec.js
@@ -0,0 +1,29 @@
+const models = require('vn-loopback/server/server').models;
+
+describe('workerTimeControl getMailStates()', () => {
+ const workerId = 9;
+ const ctx = {args: {
+ month: 12,
+ year: 2000
+ }};
+
+ it('should get the states of a month about time control mail', async() => {
+ const tx = await models.WorkerTimeControl.beginTransaction({});
+
+ try {
+ const options = {transaction: tx};
+
+ const response = await models.WorkerTimeControl.getMailStates(ctx, workerId, options);
+
+ expect(response[0].state).toEqual('REVISE');
+ expect(response[1].state).toEqual('SENDED');
+ expect(response[2].state).toEqual('CONFIRMED');
+
+ await tx.rollback();
+ } catch (e) {
+ await tx.rollback();
+ throw e;
+ }
+ });
+});
+
diff --git a/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js b/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js
index a8dc14bb1..642ff90d2 100644
--- a/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js
+++ b/modules/worker/back/methods/worker-time-control/updateWorkerTimeControlMail.js
@@ -47,6 +47,10 @@ module.exports = Self => {
if (typeof options == 'object')
Object.assign(myOptions, options);
+ const isHimself = userId == args.workerId;
+ if (!isHimself)
+ throw new UserError(`You don't have enough privileges`);
+
const workerTimeControlMail = await models.WorkerTimeControlMail.findOne({
where: {
workerFk: args.workerId,
@@ -60,8 +64,6 @@ module.exports = Self => {
const oldState = workerTimeControlMail.state;
const oldReason = workerTimeControlMail.reason;
- if (oldState == args.state) throw new UserError('Already has this status');
-
await workerTimeControlMail.updateAttributes({
state: args.state,
reason: args.reason || null
diff --git a/modules/worker/back/models/time.json b/modules/worker/back/models/time.json
index df9257540..e2f1161d7 100644
--- a/modules/worker/back/models/time.json
+++ b/modules/worker/back/models/time.json
@@ -14,6 +14,9 @@
"year": {
"type": "number"
},
+ "month": {
+ "type": "number"
+ },
"week": {
"type": "number"
}
diff --git a/modules/worker/back/models/worker-time-control.js b/modules/worker/back/models/worker-time-control.js
index 7339f5d15..5b13e17f2 100644
--- a/modules/worker/back/models/worker-time-control.js
+++ b/modules/worker/back/models/worker-time-control.js
@@ -8,6 +8,7 @@ module.exports = Self => {
require('../methods/worker-time-control/sendMail')(Self);
require('../methods/worker-time-control/updateWorkerTimeControlMail')(Self);
require('../methods/worker-time-control/weeklyHourRecordEmail')(Self);
+ require('../methods/worker-time-control/getMailStates')(Self);
Self.rewriteDbError(function(err) {
if (err.code === 'ER_DUP_ENTRY')
diff --git a/modules/worker/front/calendar/index.html b/modules/worker/front/calendar/index.html
index cff4d0bc9..c9eacbd82 100644
--- a/modules/worker/front/calendar/index.html
+++ b/modules/worker/front/calendar/index.html
@@ -25,11 +25,11 @@
{{'Contract' | translate}} #{{$ctrl.businessId}}
- {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}}
+ {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}}
- {{'Spent' | translate}} {{$ctrl.contractHolidays.hoursEnjoyed || 0}}
+ {{'Spent' | translate}} {{$ctrl.contractHolidays.hoursEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.contractHolidays.totalHours || 0}} {{'hours' | translate}}
@@ -40,11 +40,11 @@
{{'Year' | translate}} {{$ctrl.year}}
- {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}}
+ {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}}
- {{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}}
+ {{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.yearHolidays.totalHours || 0}} {{'hours' | translate}}
@@ -66,7 +66,7 @@
order="businessFk DESC"
limit="5">
- #{{businessFk}}
+ #{{businessFk}}
{{started | date: 'dd/MM/yyyy'}} - {{ended ? (ended | date: 'dd/MM/yyyy') : 'Indef.'}}
@@ -87,17 +87,17 @@
- Festive
+ Festive
- Current day
+ Current day
-
diff --git a/modules/worker/front/create/index.js b/modules/worker/front/create/index.js
index 7e837fe02..7966926b0 100644
--- a/modules/worker/front/create/index.js
+++ b/modules/worker/front/create/index.js
@@ -13,14 +13,20 @@ export default class Controller extends Section {
});
}
+ get ibanCountry() {
+ if (!this.worker || !this.worker.iban) return false;
+
+ let countryCode = this.worker.iban.substr(0, 2);
+
+ return countryCode;
+ }
+
autofillBic() {
if (!this.worker || !this.worker.iban) return;
let bankEntityId = parseInt(this.worker.iban.substr(4, 4));
let filter = {where: {id: bankEntityId}};
- if (this.ibanCountry != 'ES') return;
-
this.$http.get(`BankEntities`, {filter}).then(response => {
const hasData = response.data && response.data[0];
diff --git a/modules/worker/front/time-control/index.html b/modules/worker/front/time-control/index.html
index 681d420d0..bd7e68b89 100644
--- a/modules/worker/front/time-control/index.html
+++ b/modules/worker/front/time-control/index.html
@@ -1,7 +1,7 @@
@@ -16,7 +16,7 @@
{{::weekday.dated | date: 'MMMM'}}
-
-
+
-
-
+
-
+
+
+
+
-
+
Hours
-
-
@@ -106,6 +122,8 @@
vn-id="calendar"
class="vn-pt-md"
ng-model="$ctrl.date"
+ format-week="$ctrl.formatWeek($element)"
+ on-move="$ctrl.getMailStates($date)"
has-events="$ctrl.hasEvents($day)">
@@ -166,15 +184,31 @@
vn-id="reason"
on-accept="$ctrl.isUnsatisfied()">
-
-
+
+
+
+
-
+
-
\ No newline at end of file
+
+
+
+
+ Are you sure you want to send it?
+
+
+
+
+
+
diff --git a/modules/worker/front/time-control/index.js b/modules/worker/front/time-control/index.js
index f7379fea0..9ed454d31 100644
--- a/modules/worker/front/time-control/index.js
+++ b/modules/worker/front/time-control/index.js
@@ -1,6 +1,7 @@
import ngModule from '../module';
import Section from 'salix/components/section';
import './style.scss';
+import UserError from 'core/lib/user-error';
class Controller extends Section {
constructor($element, $, vnWeekDays) {
@@ -24,12 +25,31 @@ class Controller extends Section {
}
this.date = initialDate;
+
+ this.getMailStates(this.date);
+ }
+
+ get isHr() {
+ return this.aclService.hasAny(['hr']);
+ }
+
+ get isHimSelf() {
+ const userId = window.localStorage.currentUserWorkerId;
+ return userId == this.$params.id;
}
get worker() {
return this._worker;
}
+ get weekNumber() {
+ return this.getWeekNumber(this.date);
+ }
+
+ set weekNumber(value) {
+ this._weekNumber = value;
+ }
+
set worker(value) {
this._worker = value;
}
@@ -68,6 +88,27 @@ class Controller extends Section {
}
this.fetchHours();
+ this.getWeekData();
+ }
+
+ getWeekData() {
+ const filter = {
+ where: {
+ workerFk: this.$params.id,
+ year: this._date.getFullYear(),
+ week: this.getWeekNumber(this._date)
+ }
+ };
+ this.$http.get('WorkerTimeControlMails', {filter})
+ .then(res => {
+ const workerTimeControlMail = res.data;
+ if (!workerTimeControlMail.length) {
+ this.state = null;
+ return;
+ }
+ this.state = workerTimeControlMail[0].state;
+ this.reason = workerTimeControlMail[0].reason;
+ });
}
/**
@@ -294,42 +335,56 @@ class Controller extends Section {
this.$.editEntry.show($event);
}
- getWeekNumber(currentDate) {
- const startDate = new Date(currentDate.getFullYear(), 0, 1);
- let days = Math.floor((currentDate - startDate) /
- (24 * 60 * 60 * 1000));
- return Math.ceil(days / 7);
+ getWeekNumber(date) {
+ const tempDate = new Date(date);
+ let dayOfWeek = tempDate.getDay();
+ dayOfWeek = (dayOfWeek === 0) ? 7 : dayOfWeek;
+ const firstDayOfWeek = new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() - (dayOfWeek - 1));
+ const firstDayOfYear = new Date(tempDate.getFullYear(), 0, 1);
+ const differenceInMilliseconds = firstDayOfWeek.getTime() - firstDayOfYear.getTime();
+ const weekNumber = Math.floor(differenceInMilliseconds / (1000 * 60 * 60 * 24 * 7)) + 1;
+ return weekNumber;
}
isSatisfied() {
- const weekNumber = this.getWeekNumber(this.date);
const params = {
workerId: this.worker.id,
year: this.date.getFullYear(),
- week: weekNumber,
+ week: this.weekNumber,
state: 'CONFIRMED'
};
const query = `WorkerTimeControls/updateWorkerTimeControlMail`;
this.$http.post(query, params).then(() => {
+ this.getMailStates(this.date);
+ this.getWeekData();
this.vnApp.showSuccess(this.$t('Data saved!'));
});
}
isUnsatisfied() {
- const weekNumber = this.getWeekNumber(this.date);
+ if (!this.reason) throw new UserError(`You must indicate a reason`);
+
const params = {
workerId: this.worker.id,
year: this.date.getFullYear(),
- week: weekNumber,
+ week: this.weekNumber,
state: 'REVISE',
reason: this.reason
};
const query = `WorkerTimeControls/updateWorkerTimeControlMail`;
this.$http.post(query, params).then(() => {
+ this.getMailStates(this.date);
+ this.getWeekData();
this.vnApp.showSuccess(this.$t('Data saved!'));
});
}
+ changeState(state, reason) {
+ this.state = state;
+ this.reason = reason;
+ this.repaint();
+ }
+
save() {
try {
const entry = this.selectedRow;
@@ -345,6 +400,77 @@ class Controller extends Section {
this.vnApp.showError(this.$t(e.message));
}
}
+
+ resendEmail() {
+ const timestamp = this.date.getTime() / 1000;
+ const url = `${window.location.origin}/#!/worker/${this.worker.id}/time-control?timestamp=${timestamp}`;
+ const params = {
+ recipient: this.worker.user.emailUser.email,
+ week: this.weekNumber,
+ year: this.date.getFullYear(),
+ url: url,
+ };
+ this.$http.post(`WorkerTimeControls/weekly-hour-hecord-email`, params)
+ .then(() => {
+ this.vnApp.showSuccess(this.$t('Email sended'));
+ });
+ }
+
+ getTime(timeString) {
+ const [hours, minutes, seconds] = timeString.split(':');
+ return [parseInt(hours), parseInt(minutes), parseInt(seconds)];
+ }
+
+ getMailStates(date) {
+ const params = {
+ month: date.getMonth() + 1,
+ year: date.getFullYear()
+ };
+ const query = `WorkerTimeControls/${this.$params.id}/getMailStates`;
+ this.$http.get(query, {params})
+ .then(res => {
+ this.workerTimeControlMails = res.data;
+ this.repaint();
+ });
+ }
+
+ formatWeek($element) {
+ const weekNumberHTML = $element.firstElementChild;
+ const weekNumberValue = weekNumberHTML.innerHTML;
+
+ if (!this.workerTimeControlMails) return;
+ const workerTimeControlMail = this.workerTimeControlMails.find(
+ workerTimeControlMail => workerTimeControlMail.week == weekNumberValue
+ );
+
+ if (!workerTimeControlMail) return;
+ const state = workerTimeControlMail.state;
+
+ if (state == 'CONFIRMED') {
+ weekNumberHTML.classList.remove('revise');
+ weekNumberHTML.classList.remove('sended');
+
+ weekNumberHTML.classList.add('confirmed');
+ weekNumberHTML.setAttribute('title', 'Conforme');
+ }
+ if (state == 'REVISE') {
+ weekNumberHTML.classList.remove('confirmed');
+ weekNumberHTML.classList.remove('sended');
+
+ weekNumberHTML.classList.add('revise');
+ weekNumberHTML.setAttribute('title', 'No conforme');
+ }
+ if (state == 'SENDED') {
+ weekNumberHTML.classList.add('sended');
+ weekNumberHTML.setAttribute('title', 'Pendiente');
+ }
+ }
+
+ repaint() {
+ let calendars = this.element.querySelectorAll('vn-calendar');
+ for (let calendar of calendars)
+ calendar.$ctrl.repaint();
+ }
}
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
diff --git a/modules/worker/front/time-control/index.spec.js b/modules/worker/front/time-control/index.spec.js
index b68162d39..0f9b48f6b 100644
--- a/modules/worker/front/time-control/index.spec.js
+++ b/modules/worker/front/time-control/index.spec.js
@@ -5,12 +5,14 @@ describe('Component vnWorkerTimeControl', () => {
let $scope;
let $element;
let controller;
+ let $httpParamSerializer;
beforeEach(ngModule('worker'));
- beforeEach(inject(($componentController, $rootScope, $stateParams, _$httpBackend_) => {
+ beforeEach(inject(($componentController, $rootScope, $stateParams, _$httpBackend_, _$httpParamSerializer_) => {
$stateParams.id = 1;
$httpBackend = _$httpBackend_;
+ $httpParamSerializer = _$httpParamSerializer_;
$scope = $rootScope.$new();
$element = angular.element('');
controller = $componentController('vnWorkerTimeControl', {$element, $scope});
@@ -82,6 +84,9 @@ describe('Component vnWorkerTimeControl', () => {
$httpBackend.whenRoute('GET', 'Workers/:id/getWorkedHours')
.respond(response);
+ $httpBackend.whenRoute('GET', 'WorkerTimeControlMails')
+ .respond([]);
+
today.setHours(0, 0, 0, 0);
let weekOffset = today.getDay() - 1;
@@ -97,7 +102,6 @@ describe('Component vnWorkerTimeControl', () => {
controller.ended = ended;
controller.getWorkedHours(controller.started, controller.ended);
-
$httpBackend.flush();
expect(controller.weekDays.length).toEqual(7);
@@ -152,5 +156,120 @@ describe('Component vnWorkerTimeControl', () => {
expect(controller.date.toDateString()).toEqual(date.toDateString());
});
});
+
+ describe('getWeekData() ', () => {
+ it(`should make a query an then update the state and reason`, () => {
+ const today = Date.vnNew();
+ const response = [
+ {
+ state: 'SENDED',
+ reason: null
+ }
+ ];
+
+ controller._date = today;
+
+ $httpBackend.whenRoute('GET', 'WorkerTimeControlMails')
+ .respond(response);
+
+ controller.getWeekData();
+ $httpBackend.flush();
+
+ expect(controller.state).toBe('SENDED');
+ expect(controller.reason).toBe(null);
+ });
+ });
+
+ describe('isSatisfied() ', () => {
+ it(`should make a query an then call three methods`, () => {
+ const today = Date.vnNew();
+ jest.spyOn(controller, 'getWeekData').mockReturnThis();
+ jest.spyOn(controller, 'getMailStates').mockReturnThis();
+ jest.spyOn(controller.vnApp, 'showSuccess');
+
+ controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
+ controller.worker = {id: 1};
+ controller.date = today;
+ controller.weekNumber = 1;
+
+ $httpBackend.expect('POST', 'WorkerTimeControls/updateWorkerTimeControlMail').respond();
+ controller.isSatisfied();
+ $httpBackend.flush();
+
+ expect(controller.getMailStates).toHaveBeenCalledWith(controller.date);
+ expect(controller.getWeekData).toHaveBeenCalled();
+ expect(controller.vnApp.showSuccess).toHaveBeenCalled();
+ });
+ });
+
+ describe('isUnsatisfied() ', () => {
+ it(`should throw an error is reason is empty`, () => {
+ let error;
+ try {
+ controller.isUnsatisfied();
+ } catch (e) {
+ error = e;
+ }
+
+ expect(error).toBeDefined();
+ expect(error.message).toBe(`You must indicate a reason`);
+ });
+
+ it(`should make a query an then call three methods`, () => {
+ const today = Date.vnNew();
+ jest.spyOn(controller, 'getWeekData').mockReturnThis();
+ jest.spyOn(controller, 'getMailStates').mockReturnThis();
+ jest.spyOn(controller.vnApp, 'showSuccess');
+
+ controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
+ controller.worker = {id: 1};
+ controller.date = today;
+ controller.weekNumber = 1;
+ controller.reason = 'reason';
+
+ $httpBackend.expect('POST', 'WorkerTimeControls/updateWorkerTimeControlMail').respond();
+ controller.isSatisfied();
+ $httpBackend.flush();
+
+ expect(controller.getMailStates).toHaveBeenCalledWith(controller.date);
+ expect(controller.getWeekData).toHaveBeenCalled();
+ expect(controller.vnApp.showSuccess).toHaveBeenCalled();
+ });
+ });
+
+ describe('resendEmail() ', () => {
+ it(`should make a query an then call showSuccess method`, () => {
+ const today = Date.vnNew();
+ jest.spyOn(controller, 'getWeekData').mockReturnThis();
+ jest.spyOn(controller.vnApp, 'showSuccess');
+
+ controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
+ controller.worker = {id: 1};
+ controller.worker = {user: {emailUser: {email: 'employee@verdnatura.es'}}};
+ controller.date = today;
+ controller.weekNumber = 1;
+
+ $httpBackend.expect('POST', 'WorkerTimeControls/weekly-hour-hecord-email').respond();
+ controller.resendEmail();
+ $httpBackend.flush();
+
+ expect(controller.vnApp.showSuccess).toHaveBeenCalled();
+ });
+ });
+
+ describe('getMailStates() ', () => {
+ it(`should make a query an then call showSuccess method`, () => {
+ const today = Date.vnNew();
+ jest.spyOn(controller, 'repaint').mockReturnThis();
+
+ controller.$params = {id: 1};
+
+ $httpBackend.expect('GET', `WorkerTimeControls/1/getMailStates?month=1&year=2001`).respond();
+ controller.getMailStates(today);
+ $httpBackend.flush();
+
+ expect(controller.repaint).toHaveBeenCalled();
+ });
+ });
});
});
diff --git a/modules/worker/front/time-control/locale/es.yml b/modules/worker/front/time-control/locale/es.yml
index 2a3bffc00..091c01baa 100644
--- a/modules/worker/front/time-control/locale/es.yml
+++ b/modules/worker/front/time-control/locale/es.yml
@@ -13,4 +13,10 @@ Entry removed: Fichada borrada
The entry type can't be empty: El tipo de fichada no puede quedar vacía
Satisfied: Conforme
Not satisfied: No conforme
-Reason: Motivo
\ No newline at end of file
+Reason: Motivo
+Resend: Reenviar
+Email sended: Email enviado
+You must indicate a reason: Debes indicar un motivo
+Send time control email: Enviar email control horario
+Are you sure you want to send it?: ¿Seguro que quieres enviarlo?
+Resend email of this week to the user: Reenviar email de esta semana al usuario
diff --git a/modules/worker/front/time-control/style.scss b/modules/worker/front/time-control/style.scss
index 6a46921a7..9d7545aaf 100644
--- a/modules/worker/front/time-control/style.scss
+++ b/modules/worker/front/time-control/style.scss
@@ -14,7 +14,7 @@ vn-worker-time-control {
align-items: center;
justify-content: center;
padding: 4px 0;
-
+
& > vn-icon {
color: $color-font-secondary;
padding-right: 1px;
@@ -24,8 +24,29 @@ vn-worker-time-control {
.totalBox {
max-width: none
}
+
+}
+
+.reasonDialog{
+ min-width: 500px;
}
.edit-time-entry {
width: 200px
-}
\ No newline at end of file
+}
+
+.right {
+ float: right;
+ }
+
+.confirmed {
+ color: #97B92F;
+}
+
+.revise {
+ color: #f61e1e;
+}
+
+.sended {
+ color: #d19b25;
+}
diff --git a/modules/zone/back/models/zone.json b/modules/zone/back/models/zone.json
index 1e97c1bad..06ea5ca2b 100644
--- a/modules/zone/back/models/zone.json
+++ b/modules/zone/back/models/zone.json
@@ -38,6 +38,9 @@
"inflation": {
"type": "number"
},
+ "m3Max": {
+ "type": "number"
+ },
"itemMaxSize": {
"type": "number"
}
diff --git a/modules/zone/front/basic-data/index.html b/modules/zone/front/basic-data/index.html
index 1836216a2..8d8fc6c56 100644
--- a/modules/zone/front/basic-data/index.html
+++ b/modules/zone/front/basic-data/index.html
@@ -30,14 +30,21 @@
rule>
-
+ vn-one
+ label="Max m³"
+ ng-model="$ctrl.zone.itemMaxSize"
+ min="0"
+ vn-acl="deliveryBoss"
+ rule>
+
+
+
=0.10.0"
}
},
+ "node_modules/array-parallel": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz",
+ "integrity": "sha512-TDPTwSWW5E4oiFiKmz6RGJ/a80Y91GuLgUYuLd49+XBS75tYo8PNgaT2K/OxuQYqkoI852MDGBorg9OcUSTQ8w=="
+ },
+ "node_modules/array-series": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz",
+ "integrity": "sha512-L0XlBwfx9QetHOsbLDrE/vh2t018w9462HM3iaFfxRiK83aJjAt/Ja3NMkOW7FICwWTlQBa3ZbL5FKhuQWkDrg=="
+ },
"node_modules/array-slice": {
"version": "1.1.0",
"dev": true,
@@ -9284,6 +9295,67 @@
"node": ">= 0.10"
}
},
+ "node_modules/gm": {
+ "version": "1.25.0",
+ "resolved": "https://registry.npmjs.org/gm/-/gm-1.25.0.tgz",
+ "integrity": "sha512-4kKdWXTtgQ4biIo7hZA396HT062nDVVHPjQcurNZ3o/voYN+o5FUC5kOwuORbpExp3XbTJ3SU7iRipiIhQtovw==",
+ "dependencies": {
+ "array-parallel": "~0.1.3",
+ "array-series": "~0.1.5",
+ "cross-spawn": "^4.0.0",
+ "debug": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/gm/node_modules/cross-spawn": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
+ "integrity": "sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA==",
+ "dependencies": {
+ "lru-cache": "^4.0.1",
+ "which": "^1.2.9"
+ }
+ },
+ "node_modules/gm/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/gm/node_modules/lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dependencies": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "node_modules/gm/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/gm/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/gm/node_modules/yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
+ },
"node_modules/google-auth-library": {
"version": "3.1.2",
"license": "Apache-2.0",
@@ -28673,6 +28745,16 @@
}
}
},
+ "array-parallel": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz",
+ "integrity": "sha512-TDPTwSWW5E4oiFiKmz6RGJ/a80Y91GuLgUYuLd49+XBS75tYo8PNgaT2K/OxuQYqkoI852MDGBorg9OcUSTQ8w=="
+ },
+ "array-series": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz",
+ "integrity": "sha512-L0XlBwfx9QetHOsbLDrE/vh2t018w9462HM3iaFfxRiK83aJjAt/Ja3NMkOW7FICwWTlQBa3ZbL5FKhuQWkDrg=="
+ },
"array-slice": {
"version": "1.1.0",
"dev": true
@@ -32611,6 +32693,63 @@
"sparkles": "^1.0.0"
}
},
+ "gm": {
+ "version": "1.25.0",
+ "resolved": "https://registry.npmjs.org/gm/-/gm-1.25.0.tgz",
+ "integrity": "sha512-4kKdWXTtgQ4biIo7hZA396HT062nDVVHPjQcurNZ3o/voYN+o5FUC5kOwuORbpExp3XbTJ3SU7iRipiIhQtovw==",
+ "requires": {
+ "array-parallel": "~0.1.3",
+ "array-series": "~0.1.5",
+ "cross-spawn": "^4.0.0",
+ "debug": "^3.1.0"
+ },
+ "dependencies": {
+ "cross-spawn": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
+ "integrity": "sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA==",
+ "requires": {
+ "lru-cache": "^4.0.1",
+ "which": "^1.2.9"
+ }
+ },
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "requires": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
+ }
+ }
+ },
"google-auth-library": {
"version": "3.1.2",
"requires": {
diff --git a/package.json b/package.json
index 30c8039ac..3d0fc4aed 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "salix-back",
- "version": "23.10.01",
+ "version": "23.12.01",
"author": "Verdnatura Levante SL",
"description": "Salix backend",
"license": "GPL-3.0",
@@ -20,6 +20,7 @@
"form-data": "^4.0.0",
"fs-extra": "^5.0.0",
"ftps": "^1.2.0",
+ "gm": "^1.25.0",
"got": "^10.7.0",
"helmet": "^3.21.2",
"i18n": "^0.8.4",
diff --git a/print/templates/reports/balance-compensation/balance-compensation.html b/print/templates/reports/balance-compensation/balance-compensation.html
index d1a2788ed..c7448eeb9 100644
--- a/print/templates/reports/balance-compensation/balance-compensation.html
+++ b/print/templates/reports/balance-compensation/balance-compensation.html
@@ -17,8 +17,8 @@
{{$t('Agree') | uppercase}}
- {{$t('Date')}} {{client.payed | date('%d-%m-%Y')}} {{$t('Compensate')}} {{client.amountPaid}} €
- {{$t('From client')}} {{client.name}} {{$t('Against the balance of')}}: {{client.invoiceFk}}.
+ {{$t('Date')}} {{formatDate(receipt.payed, '%d-%m-%Y')}} {{$t('Compensate')}} {{receipt.amountPaid}} €
+ {{$t('From client')}} {{client.name}} {{$t('Against the balance of')}}: {{receipt.description}}.
{{$t('Reception')}} administracion@verdnatura.es
diff --git a/print/templates/reports/balance-compensation/balance-compensation.js b/print/templates/reports/balance-compensation/balance-compensation.js
index bae7c5c3c..c2c2e9288 100644
--- a/print/templates/reports/balance-compensation/balance-compensation.js
+++ b/print/templates/reports/balance-compensation/balance-compensation.js
@@ -1,12 +1,31 @@
const vnReport = require('../../../core/mixins/vn-report.js');
+const app = require('vn-loopback/server/server');
module.exports = {
name: 'balance-compensation',
mixins: [vnReport],
async serverPrefetch() {
- this.client = await this.findOneFromDef('client', [this.id]);
- this.checkMainEntity(this.client);
- this.company = await this.findOneFromDef('company', [this.id]);
+ this.receipt = await app.models.Receipt.findOne({
+ fields: ['amountPaid', 'payed', 'clientFk', 'companyFk', 'description'],
+ include: [
+ {
+ relation: 'client',
+ scope: {
+ fields: ['name', 'street', 'fi', 'city'],
+ }
+ }, {
+ relation: 'supplier',
+ scope: {
+ fields: ['name', 'street', 'nif', 'city'],
+ }
+ }
+ ],
+ where: {id: this.id}
+ });
+ this.client = this.receipt.client();
+ this.company = this.receipt.supplier();
+
+ this.checkMainEntity(this.receipt);
},
props: {
id: {
diff --git a/print/templates/reports/balance-compensation/sql/client.sql b/print/templates/reports/balance-compensation/sql/client.sql
deleted file mode 100644
index c3679b68a..000000000
--- a/print/templates/reports/balance-compensation/sql/client.sql
+++ /dev/null
@@ -1,12 +0,0 @@
-SELECT
- c.name,
- c.socialName,
- c.street,
- c.fi,
- c.city,
- r.invoiceFk,
- r.amountPaid,
- r.payed
- FROM client c
- JOIN receipt r ON r.clientFk = c.id
- WHERE r.id = ?
diff --git a/print/templates/reports/balance-compensation/sql/company.sql b/print/templates/reports/balance-compensation/sql/company.sql
deleted file mode 100644
index e61228a10..000000000
--- a/print/templates/reports/balance-compensation/sql/company.sql
+++ /dev/null
@@ -1,8 +0,0 @@
-SELECT
- s.name,
- s.nif,
- s.street,
- s.city
- FROM supplier s
- JOIN receipt r ON r.companyFk = s.id
- WHERE r.id = ?;
\ No newline at end of file
diff --git a/print/templates/reports/extra-community/extra-community.html b/print/templates/reports/extra-community/extra-community.html
index cd61a4f4d..3153b6b03 100644
--- a/print/templates/reports/extra-community/extra-community.html
+++ b/print/templates/reports/extra-community/extra-community.html
@@ -51,7 +51,7 @@
{{entry.supplierName}} |
{{entry.reference}} |
{{entry.volumeKg | number($i18n.locale)}} |
- {{entry.loadedKg | number($i18n.locale)}} |
+ {{entry.loadedkg | number($i18n.locale)}} |
{{entry.stickers}} |
diff --git a/print/templates/reports/extra-community/extra-community.js b/print/templates/reports/extra-community/extra-community.js
index 9941faa35..5d875d78f 100755
--- a/print/templates/reports/extra-community/extra-community.js
+++ b/print/templates/reports/extra-community/extra-community.js
@@ -1,11 +1,12 @@
const vnReport = require('../../../core/mixins/vn-report.js');
-const db = require(`vn-print/core/database`);
+const app = require('vn-loopback/server/server');
module.exports = {
name: 'extra-community',
mixins: [vnReport],
async serverPrefetch() {
const args = {
+ search: this.search,
landedTo: this.landedEnd,
shippedFrom: this.shippedStart,
continent: this.continent,
@@ -17,76 +18,24 @@ module.exports = {
ref: this.ref,
cargoSupplierFk: this.cargoSupplierFk
};
-
- const travels = await this.fetchTravels(args);
- this.checkMainEntity(travels);
- const travelIds = travels.map(travel => travel.id);
- const entries = await this.rawSqlFromDef('entries', [travelIds]);
-
- const map = new Map();
- for (let travel of travels)
- map.set(travel.id, travel);
-
- for (let entry of entries) {
- const travel = map.get(entry.travelFk);
- if (!travel.entries) travel.entries = [];
- travel.entries.push(entry);
- }
-
- this.travels = travels;
+ const ctx = {args: args};
+ this.travels = await app.models.Travel.extraCommunityFilter(ctx, this.filter);
},
computed: {
landedEnd: function() {
if (!this.landedTo) return;
- return formatDate(this.landedTo, '%Y-%m-%d');
+ return this.formatDate(this.landedTo, '%Y-%m-%d');
},
shippedStart: function() {
if (!this.shippedFrom) return;
- return formatDate(this.shippedFrom, '%Y-%m-%d');
+ return this.formatDate(this.shippedFrom, '%Y-%m-%d');
}
},
methods: {
- fetchTravels(args) {
- const where = db.buildWhere(args, (key, value) => {
- switch (key) {
- case 'shippedFrom':
- return `t.shipped >= ${value}`;
- case 'landedTo':
- return `t.landed <= ${value}`;
- case 'continent':
- return `cnt.code = ${value}`;
- case 'ref':
- return {'t.ref': {like: `%${value}%`}};
- case 'id':
- return `t.id = ${value}`;
- case 'agencyModeFk':
- return `am.id = ${value}`;
- case 'warehouseOutFk':
- return `wo.id = ${value}`;
- case 'warehouseInFk':
- return `w.id = ${value}`;
- case 'cargoSupplierFk':
- return `s.id = ${value}`;
- }
- });
-
- let query = this.getSqlFromDef('travels');
- query = db.merge(query, where);
- query = db.merge(query, 'GROUP BY t.id');
- query = db.merge(query, `
- ORDER BY
- shipped ASC,
- landed ASC,
- travelFk,
- loadPriority,
- agencyModeFk,
- evaNotes
- `);
-
- return this.rawSql(query);
- },
},
props: [
+ 'filter',
+ 'search',
'landedTo',
'shippedFrom',
'continent',
diff --git a/print/templates/reports/extra-community/sql/entries.sql b/print/templates/reports/extra-community/sql/entries.sql
deleted file mode 100644
index 84dc497c0..000000000
--- a/print/templates/reports/extra-community/sql/entries.sql
+++ /dev/null
@@ -1,18 +0,0 @@
-SELECT
- e.id,
- e.travelFk,
- e.reference,
- s.name AS supplierName,
- SUM(b.stickers) AS stickers,
- CAST(SUM(b.weight * b.stickers) as DECIMAL(10,0)) as loadedKg,
- CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) as DECIMAL(10,0)) as volumeKg
- FROM travel t
- JOIN entry e ON e.travelFk = t.id
- JOIN buy b ON b.entryFk = e.id
- JOIN packaging pkg ON pkg.id = b.packageFk
- JOIN item i ON i.id = b.itemFk
- JOIN itemType it ON it.id = i.typeFk
- JOIN supplier s ON s.id = e.supplierFk
- JOIN vn.volumeConfig vc
- WHERE t.id IN(?)
- GROUP BY e.id
diff --git a/print/templates/reports/extra-community/sql/travels.sql b/print/templates/reports/extra-community/sql/travels.sql
deleted file mode 100644
index b0987c330..000000000
--- a/print/templates/reports/extra-community/sql/travels.sql
+++ /dev/null
@@ -1,23 +0,0 @@
-SELECT
- t.id,
- t.ref,
- t.shipped,
- t.landed,
- t.kg,
- am.id AS agencyModeFk,
- SUM(b.stickers) AS stickers,
- CAST(SUM(b.weight * b.stickers) as DECIMAL(10,0)) as loadedKg,
- CAST(SUM(vc.aerealVolumetricDensity * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000) as DECIMAL(10,0)) as volumeKg
-FROM travel t
- JOIN volumeConfig vc
- LEFT JOIN supplier s ON s.id = t.cargoSupplierFk
- LEFT JOIN entry e ON e.travelFk = t.id
- LEFT JOIN buy b ON b.entryFk = e.id
- LEFT JOIN packaging pkg ON pkg.id = b.packageFk
- LEFT JOIN item i ON i.id = b.itemFk
- LEFT JOIN itemType it ON it.id = i.typeFk
- JOIN warehouse w ON w.id = t.warehouseInFk
- JOIN warehouse wo ON wo.id = t.warehouseOutFk
- JOIN country c ON c.id = wo.countryFk
- LEFT JOIN continent cnt ON cnt.id = c.continentFk
- JOIN agencyMode am ON am.id = t.agencyModeFk
\ No newline at end of file