6014-executeRoutineMethod #1809

Merged
alexm merged 8 commits from 6014-executeRoutineMethod into dev 2023-11-14 08:45:07 +00:00
190 changed files with 2594 additions and 1661 deletions
Showing only changes of commit 4aac9f93cc - Show all commits

View File

@ -5,21 +5,29 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2342.01] - 2023-10-19 ## [2348.01] - 2023-11-30
### Added ### Added
### Changed ### Changed
### Fixed ### Fixed
## [2340.01] - 2023-10-05 ## [2346.01] - 2023-11-16
### Added
### Changed
### Fixed
## [2342.01] - 2023-11-02
### Added ### Added
- (Usuarios -> Foto) Se muestra la foto del trabajador - (Usuarios -> Foto) Se muestra la foto del trabajador
### Changed
### Fixed ### Fixed
- (Usuarios -> Historial) Abre el descriptor del usuario correctamente - (Usuarios -> Historial) Abre el descriptor del usuario correctamente
## [2340.01] - 2023-10-05
## [2338.01] - 2023-09-21 ## [2338.01] - 2023-09-21
### Added ### Added
@ -29,17 +37,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- (Trabajadores -> Calendario) Icono de check arreglado cuando pulsas un tipo de dia - (Trabajadores -> Calendario) Icono de check arreglado cuando pulsas un tipo de dia
### Fixed
## [2336.01] - 2023-09-07 ## [2336.01] - 2023-09-07
### Added
### Changed
### Fixed
## [2334.01] - 2023-08-24 ## [2334.01] - 2023-08-24
### Added ### Added

View File

@ -26,15 +26,14 @@ module.exports = Self => {
Self.sendCheckingPresence = async(ctx, recipientId, message) => { Self.sendCheckingPresence = async(ctx, recipientId, message) => {
if (!recipientId) return false; if (!recipientId) return false;
const models = Self.app.models; const models = Self.app.models;
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const sender = await models.VnUser.findById(userId, {fields: ['id']}); const sender = await models.VnUser.findById(userId, {fields: ['id']});
const recipient = await models.VnUser.findById(recipientId, null); const recipient = await models.VnUser.findById(recipientId, null);
// Prevent sending messages to yourself // Prevent sending messages to yourself
if (recipientId == userId) return false; if (recipientId == userId) return false;
if (!recipient) if (!recipient)
throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`); throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`);

View File

@ -26,7 +26,7 @@ module.exports = Self => {
Self.getTickets = async(ctx, id, print, options) => { Self.getTickets = async(ctx, id, print, options) => {
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const origin = ctx.req.headers.origin; const url = await Self.app.models.Url.getUrl();
const $t = ctx.req.__; const $t = ctx.req.__;
const myOptions = {}; const myOptions = {};
@ -36,7 +36,6 @@ module.exports = Self => {
myOptions.userId = userId; myOptions.userId = userId;
const promises = []; const promises = [];
const [tickets] = await Self.rawSql(`CALL vn.collection_getTickets(?)`, [id], myOptions); const [tickets] = await Self.rawSql(`CALL vn.collection_getTickets(?)`, [id], myOptions);
const sales = await Self.rawSql(` const sales = await Self.rawSql(`
SELECT s.ticketFk, SELECT s.ticketFk,
@ -86,24 +85,19 @@ module.exports = Self => {
if (tickets && tickets.length) { if (tickets && tickets.length) {
for (const ticket of tickets) { for (const ticket of tickets) {
const ticketId = ticket.ticketFk; const ticketId = ticket.ticketFk;
// SEND ROCKET
if (ticket.observaciones != '') { if (ticket.observaciones != '') {
for (observation of ticket.observaciones.split(' ')) { for (observation of ticket.observaciones.split(' ')) {
if (['#', '@'].includes(observation.charAt(0))) { if (['#', '@'].includes(observation.charAt(0))) {
promises.push(Self.app.models.Chat.send(ctx, observation, promises.push(Self.app.models.Chat.send(ctx, observation,
$t('The ticket is in preparation', { $t('The ticket is in preparation', {
ticketId: ticketId, ticketId: ticketId,
ticketUrl: `${origin}/#!/ticket/${ticketId}/summary`, ticketUrl: `${url}ticket/${ticketId}/summary`,
salesPersonId: ticket.salesPersonFk salesPersonId: ticket.salesPersonFk
}))); })));
} }
} }
} }
// SET COLLECTION
if (sales && sales.length) { if (sales && sales.length) {
// GET BARCODES
const barcodes = await Self.rawSql(` const barcodes = await Self.rawSql(`
SELECT s.id saleFk, b.code, c.id SELECT s.id saleFk, b.code, c.id
FROM vn.sale s FROM vn.sale s
@ -114,13 +108,10 @@ module.exports = Self => {
WHERE s.ticketFk = ? WHERE s.ticketFk = ?
AND tr.landed >= util.VN_CURDATE() - INTERVAL 1 YEAR`, AND tr.landed >= util.VN_CURDATE() - INTERVAL 1 YEAR`,
[ticketId], myOptions); [ticketId], myOptions);
// BINDINGS
ticket.sales = []; ticket.sales = [];
for (const sale of sales) { for (const sale of sales) {
if (sale.ticketFk === ticketId) { if (sale.ticketFk === ticketId) {
sale.Barcodes = []; sale.Barcodes = [];
if (barcodes && barcodes.length) { if (barcodes && barcodes.length) {
for (const barcode of barcodes) { for (const barcode of barcodes) {
if (barcode.saleFk === sale.saleFk) { if (barcode.saleFk === sale.saleFk) {
@ -131,7 +122,6 @@ module.exports = Self => {
} }
} }
} }
ticket.sales.push(sale); ticket.sales.push(sale);
} }
} }
@ -140,7 +130,6 @@ module.exports = Self => {
} }
} }
await Promise.all(promises); await Promise.all(promises);
return collection; return collection;
}; };
}; };

View File

@ -0,0 +1,30 @@
module.exports = Self => {
Self.remoteMethod('getUrl', {
description: 'Returns the colling app name',
accessType: 'READ',
accepts: [
{
arg: 'app',
type: 'string',
required: false
}
],
returns: {
type: 'object',
root: true
},
http: {
path: `/getUrl`,
verb: 'get'
}
});
Self.getUrl = async(appName = 'salix') => {
const {url} = await Self.app.models.Url.findOne({
where: {
appName,
enviroment: process.env.NODE_ENV || 'development'
}
});
return url;
};
};

View File

@ -7,17 +7,14 @@ module.exports = Self => {
Self.observe('before save', async function(ctx) { Self.observe('before save', async function(ctx) {
if (!ctx.isNewInstance) return; if (!ctx.isNewInstance) return;
let {message} = ctx.instance; let {message} = ctx.instance;
if (!message) return; if (!message) return;
const parts = message.match(/(?<=\[)[a-zA-Z0-9_\-+!@#$%^&*()={};':"\\|,.<>/?\s]*(?=])/g); const parts = message.match(/(?<=\[)[a-zA-Z0-9_\-+!@#$%^&*()={};':"\\|,.<>/?\s]*(?=])/g);
if (!parts) return; if (!parts) return;
const replacedParts = parts.map(part => { const replacedParts = parts.map(part => {
return part.replace(/[!$%^&*()={};':"\\,.<>/?]/g, ''); return part.replace(/[!$%^&*()={};':"\\,.<>/?]/g, '');
}); });
for (const [index, part] of parts.entries()) for (const [index, part] of parts.entries())
message = message.replace(part, replacedParts[index]); message = message.replace(part, replacedParts[index]);

View File

@ -1,3 +1,4 @@
module.exports = Self => { module.exports = Self => {
require('../methods/url/getByUser')(Self); require('../methods/url/getByUser')(Self);
require('../methods/url/getUrl')(Self);
}; };

View File

@ -1,7 +1,7 @@
const vnModel = require('vn-loopback/common/models/vn-model'); const vnModel = require('vn-loopback/common/models/vn-model');
const LoopBackContext = require('loopback-context');
const {Email} = require('vn-print'); const {Email} = require('vn-print');
const ForbiddenError = require('vn-loopback/util/forbiddenError'); const ForbiddenError = require('vn-loopback/util/forbiddenError');
const LoopBackContext = require('loopback-context');
module.exports = function(Self) { module.exports = function(Self) {
vnModel(Self); vnModel(Self);
@ -92,11 +92,7 @@ module.exports = function(Self) {
}; };
Self.on('resetPasswordRequest', async function(info) { Self.on('resetPasswordRequest', async function(info) {
const loopBackContext = LoopBackContext.getCurrentContext(); const url = await Self.app.models.Url.getUrl();
const httpCtx = {req: loopBackContext.active};
const httpRequest = httpCtx.req.http.req;
const headers = httpRequest.headers;
const origin = headers.origin;
const defaultHash = '/reset-password?access_token=$token$'; const defaultHash = '/reset-password?access_token=$token$';
const recoverHashes = { const recoverHashes = {
@ -112,7 +108,7 @@ module.exports = function(Self) {
const params = { const params = {
recipient: info.email, recipient: info.email,
lang: user.lang, lang: user.lang,
url: origin + '/#!' + recoverHash url: url.slice(0, -1) + recoverHash
}; };
const options = Object.assign({}, info.options); const options = Object.assign({}, info.options);

View File

@ -0,0 +1,133 @@
DELIMITER $$
$$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canAdvance`(vDateFuture DATE, vDateToAdvance DATE, vWarehouseFk INT)
BEGIN
/**
* Devuelve los tickets y la cantidad de lineas de venta que se pueden adelantar.
*
* @param vDateFuture Fecha de los tickets que se quieren adelantar.
* @param vDateToAdvance Fecha a cuando se quiere adelantar.
* @param vWarehouseFk Almacén
*/
DECLARE vDateInventory DATE;
SELECT inventoried INTO vDateInventory FROM config;
DROP TEMPORARY TABLE IF EXISTS tmp.stock;
CREATE TEMPORARY TABLE tmp.stock
(itemFk INT PRIMARY KEY,
amount INT)
ENGINE = MEMORY;
INSERT INTO tmp.stock(itemFk, amount)
SELECT itemFk, SUM(quantity) amount FROM
(
SELECT itemFk, quantity
FROM itemTicketOut
WHERE shipped >= vDateInventory
AND shipped < vDateFuture
AND warehouseFk = vWarehouseFk
UNION ALL
SELECT itemFk, quantity
FROM itemEntryIn
WHERE landed >= vDateInventory
AND landed < vDateFuture
AND isVirtualStock = FALSE
AND warehouseInFk = vWarehouseFk
UNION ALL
SELECT itemFk, quantity
FROM itemEntryOut
WHERE shipped >= vDateInventory
AND shipped < vDateFuture
AND warehouseOutFk = vWarehouseFk
) t
GROUP BY itemFk HAVING amount != 0;
CREATE OR REPLACE TEMPORARY TABLE tmp.filter
(INDEX (id))
SELECT
origin.ticketFk futureId,
dest.ticketFk id,
dest.state,
origin.futureState,
origin.futureIpt,
dest.ipt,
origin.workerFk,
origin.futureLiters,
origin.futureLines,
dest.shipped,
origin.shipped futureShipped,
dest.totalWithVat,
origin.totalWithVat futureTotalWithVat,
dest.agency,
origin.futureAgency,
dest.lines,
dest.liters,
origin.futureLines - origin.hasStock AS notMovableLines,
(origin.futureLines = origin.hasStock) AS isFullMovable,
origin.futureZoneFk,
origin.futureZoneName,
origin.classColor futureClassColor,
dest.classColor
FROM (
SELECT
s.ticketFk,
c.salesPersonFk workerFk,
t.shipped,
t.totalWithVat,
st.name futureState,
t.addressFk,
am.name futureAgency,
count(s.id) futureLines,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt,
CAST(SUM(litros) AS DECIMAL(10,0)) futureLiters,
SUM((s.quantity <= IFNULL(st.amount,0))) hasStock,
z.id futureZoneFk,
z.name futureZoneName,
st.classColor
FROM ticket t
JOIN client c ON c.id = t.clientFk
JOIN sale s ON s.ticketFk = t.id
JOIN saleVolume sv ON sv.saleFk = s.id
JOIN item i ON i.id = s.itemFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN state st ON st.id = ts.stateFk
JOIN agencyMode am ON t.agencyModeFk = am.id
JOIN zone z ON t.zoneFk = z.id
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
LEFT JOIN tmp.stock st ON st.itemFk = i.id
WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture)
AND t.warehouseFk = vWarehouseFk
GROUP BY t.id
) origin
JOIN (
SELECT
t.id ticketFk,
t.addressFk,
st.name state,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) ipt,
t.shipped,
t.totalWithVat,
am.name agency,
CAST(SUM(litros) AS DECIMAL(10,0)) liters,
CAST(COUNT(*) AS DECIMAL(10,0)) `lines`,
st.classColor
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN saleVolume sv ON sv.saleFk = s.id
JOIN item i ON i.id = s.itemFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN state st ON st.id = ts.stateFk
JOIN agencyMode am ON t.agencyModeFk = am.id
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
WHERE t.shipped BETWEEN vDateToAdvance AND util.dayend(vDateToAdvance)
AND t.warehouseFk = vWarehouseFk
AND st.order <= 5
GROUP BY t.id
) dest ON dest.addressFk = origin.addressFk
WHERE origin.hasStock != 0;
DROP TEMPORARY TABLE tmp.stock;
END$$
DELIMITER ;

View File

View File

@ -0,0 +1,41 @@
UPDATE `vn`.`workerTimeControlConfig`
SET `timeToBreakTime` = 18000;
ALTER TABLE `vn`.`workerTimeControlConfig`
DROP COLUMN IF EXISTS `maxTimeToBreak`;
ALTER TABLE `vn`.`workerTimeControlConfig`
ADD COLUMN maxTimeToBreak INT DEFAULT 3600 NULL;
ALTER TABLE `vn`.`workerTimeControlConfig`
DROP COLUMN IF EXISTS `maxWorkShortCycle`;
ALTER TABLE `vn`.`workerTimeControlConfig`
ADD COLUMN `maxWorkShortCycle` INT(10) UNSIGNED DEFAULT 561600
COMMENT 'Máximo tiempo que un trabajador puede estar trabajando con el que adquirirá el derecho a un descanso semanal corto';
ALTER TABLE `vn`.`workerTimeControlConfig`
DROP COLUMN IF EXISTS `maxWorkLongCycle`;
ALTER TABLE `vn`.`workerTimeControlConfig`
ADD COLUMN `maxWorkLongCycle` INT(10) UNSIGNED DEFAULT 950400
COMMENT 'Máximo tiempo que un trabajador puede estar trabajando con el que adquirirá el derecho a un descanso semanal largo';
CREATE TABLE IF NOT EXISTS `vn`.`workerTimeControlError` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`code` char(35) NOT NULL,
`description` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `code` (`code`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
INSERT IGNORE INTO `vn`.`workerTimeControlError` (`code`, `description`)
VALUES
('IS_NOT_ALLOWED_FUTURE', 'No se permite fichar a futuro'),
('INACTIVE_BUSINESS', 'No hay un contrato en vigor'),
('IS_NOT_ALLOWED_WORK', 'No está permitido trabajar'),
('ODD_WORKERTIMECONTROL', 'Fichadas impares'),
('DAY_MAX_TIME', 'Superado el tiempo máximo entre entrada y salida'),
('BREAK_DAY', 'Descanso diario'),
('BREAK_WEEK', 'Descanso semanal'),
('WRONG_DIRECTION', 'Dirección incorrecta'),
('UNDEFINED_ERROR', 'Error sin definir');

View File

@ -0,0 +1,194 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`timeControl_calculate`(
vDatedFrom DATETIME,
vDatedTo DATETIME)
BEGIN
/*
* Agrupa por trabajador y día, el tiempo de trabajo y descanso retribuido(si tiene).
* Los registros horarios incorrectos (tmp.timeControlError) no se considerarán.
* Si un trabajador ha trabajado más de un cierto umbral de tiempo (vTimeToBreakTime)
* y no ha tenido descansos que superen un parámetro determinado(vMaxTimeToBreak),
* se le añadirá un tiempo de descanso (vBreakTime) a sus horas trabajadas.
* El tiempo de descanso solo se añade si el trabajador realmente disfrutó del descanso.
* Si disfrutó de menos tiempo de descanso, solo se añade el tiempo que disfrutó.
*
* @param vDatedFrom
* @param vDatedTo
*
* @return tmp.timeControlCalculate
* (workerFk, dated, timeWorkSeconds, timeWorkSexagesimal, timeWorkDecimal, timed)
*/
DECLARE vHourSeconds INTEGER;
DECLARE vDatedFromYesterday DATETIME;
DECLARE vDatedToTomorrow DATETIME;
DECLARE vTimeToBreakTime INT;
DECLARE vBreakTime INT;
DECLARE vMaxTimeToBreak INT;
SELECT DATE_SUB(vDatedFrom, INTERVAL 1 DAY), DATE_ADD(vDatedTo, INTERVAL 1 DAY)
INTO vDatedFromYesterday, vDatedToTomorrow;
SELECT timeToBreakTime, breakTime, maxTimeToBreak, TIME_TO_SEC('01:00:00')
INTO vTimeToBreakTime, vBreakTime, vMaxTimeToBreak, vHourSeconds
FROM workerTimeControlConfig
LIMIT 1;
CALL timeControl_getError(vDatedFromYesterday, vDatedToTomorrow);
CREATE OR REPLACE TEMPORARY TABLE tmp.workerTimeControl
(INDEX(userFk, timed), INDEX(timed), INDEX(direction))
ENGINE = MEMORY
SELECT wtc.userFk,
wtc.timed,
DATE(wtc.timed) dated,
wtc.direction,
TRUE isReal
FROM workerTimeControl wtc
JOIN tmp.`user` u ON u.userFk = wtc.userFk
LEFT JOIN (
SELECT wtc.userFk, MIN(wtc.timed) firstIn
FROM workerTimeControl wtc
JOIN tmp.`user` u ON u.userFk = wtc.userFk
LEFT JOIN tmp.timeControlError tce ON tce.id = wtc.id
WHERE wtc.timed BETWEEN vDatedFromYesterday AND vDatedToTomorrow
AND wtc.direction = 'in'
AND tce.id IS NULL
GROUP BY userFk
) fi ON wtc.userFk = fi.userFk
LEFT JOIN (
SELECT wtc.userFk, MAX(wtc.timed) lastOut
FROM workerTimeControl wtc
JOIN tmp.`user` u ON u.userFk = wtc.userFk
LEFT JOIN tmp.timeControlError tce ON tce.id = wtc.id
WHERE wtc.timed BETWEEN vDatedFromYesterday AND vDatedToTomorrow
AND wtc.direction = 'out'
AND tce.id IS NULL
GROUP BY userFk
) lo ON wtc.userFk = lo.userFk
LEFT JOIN tmp.timeControlError tce ON tce.id = wtc.id
WHERE wtc.timed BETWEEN fi.firstIn AND lo.lastOut
AND tce.id IS NULL
ORDER BY wtc.userFk, wtc.timed;
CREATE OR REPLACE TEMPORARY TABLE tmp.wtcToinsert
(INDEX(timed))
ENGINE = MEMORY
WITH wtc AS(
SELECT timed,
userFk,
dated,
direction,
LEAD(dated) OVER
(PARTITION BY userFk, dated ORDER BY timed) nextDay,
LEAD(userFk) OVER
(PARTITION BY userFk ORDER BY timed) nextUserFk,
ROW_NUMBER() OVER (ORDER BY userFk, timed) MOD 2 isOdd
FROM tmp.workerTimeControl
WHERE timed BETWEEN vDatedFromYesterday AND vDatedToTomorrow
ORDER BY userFk, timed
), wtcToinsert AS(
SELECT userFk,
dated,
IF(userFk = nextUserFk
AND nextDay IS NULL
AND isOdd
AND direction <> 'out', TRUE, FALSE) outNextDay,
IF(userFk = nextUserFk
AND nextDay IS NULL
AND NOT isOdd
AND direction <> 'out', TRUE, FALSE) outNextDayWhitBreak
FROM wtc
HAVING outNextDay OR outNextDayWhitBreak
)SELECT userFk, util.dayEnd(dated) timed, 'out' direction
FROM wtcToinsert
WHERE outNextDay
UNION ALL
SELECT userFk, dated + INTERVAL 1 DAY, 'in'
FROM wtcToinsert
WHERE outNextDay
UNION ALL
SELECT userFk, util.dayEnd(dated) - INTERVAL 1 SECOND, 'middle'
FROM wtcToinsert
WHERE outNextDayWhitBreak
UNION ALL
SELECT userFk, util.dayEnd(dated), 'out'
FROM wtcToinsert
WHERE outNextDayWhitBreak
UNION ALL
SELECT userFk, dated + INTERVAL 1 DAY, 'in'
FROM wtcToinsert
WHERE outNextDayWhitBreak
UNION ALL
SELECT userFk, dated + INTERVAL 1 DAY + INTERVAL 1 SECOND, 'middle'
FROM wtcToinsert
WHERE outNextDayWhitBreak;
INSERT INTO tmp.workerTimeControl (userFk, timed, dated, direction, isReal)
SELECT userFk, timed, DATE(timed), direction, FALSE
FROM tmp.wtcToinsert;
SET @accumulatedForBreakTime = 0;
SET @oldrealDay = NULL;
CREATE OR REPLACE TEMPORARY TABLE tmp.timeControlCalculate
WITH workerTimed AS (
SELECT
userFk,
dated,
timed,
(direction ='in' AND isReal) breakPoint,
SUM(CASE WHEN (direction ='in' AND isReal) THEN TRUE ELSE FALSE END)
OVER (ORDER BY userFk, timed) AS realDay,
TIMESTAMPDIFF(SECOND, LAG(timed)
OVER (PARTITION BY userFk, dated ORDER BY timed), timed) gapTime,
ROW_NUMBER()
OVER (PARTITION BY userFk, dated ORDER BY timed) MOD 2 isOdd
FROM tmp.workerTimeControl
WHERE timed BETWEEN vDatedFromYesterday AND vDatedToTomorrow
), accumulated AS (
SELECT SUM(IF(isOdd, 0, gapTime))
OVER (PARTITION BY userFk,dated ORDER BY userFk,timed) accumulatedWorkTime,
SUM(IF(NOT isOdd OR breakPoint, 0, IFNULL(gapTime, 0)))
OVER (PARTITION BY realDay ORDER BY realDay,timed) accumulatedBreakTime,
IF(realDay <> @oldrealDay OR (isOdd AND gapTime >= vMaxTimeToBreak),
@accumulatedForBreakTime := 0,
@accumulatedForBreakTime := @accumulatedForBreakTime +
IF(isOdd, 0, gapTime )) accumulatedForBreakTime,
@oldrealDay := realDay,
userFk,
dated,
realDay
FROM workerTimed
), totalWorked AS (
SELECT userFk,
dated,
MAX(accumulatedWorkTime) +
IF(MAX(accumulatedForBreakTime) >= vTimeToBreakTime,
LEAST(vBreakTime, MAX(accumulatedBreakTime)),
0) timeWorkSeconds
FROM accumulated
GROUP BY userFk, dated
)SELECT tw.userFk,
tw.dated,
timeWorkSeconds,
SEC_TO_TIME(timeWorkSeconds) timeWorkSexagesimal,
timeWorkSeconds / vHourSeconds timeWorkDecimal,
sub.tableTimed
FROM totalWorked tw
JOIN (
SELECT userFk,
dated,
GROUP_CONCAT(DATE_FORMAT(timed, "%H:%i") ORDER BY timed ASC
SEPARATOR ' - ')tableTimed
FROM tmp.workerTimeControl
WHERE timed BETWEEN vDatedFromYesterday AND vDatedToTomorrow
AND isReal
GROUP BY userFk, dated
)sub ON sub.dated = tw.dated
AND sub.userFk = tw.userFk
WHERE tw.dated BETWEEN vDatedFrom AND vDatedTo;
DROP TEMPORARY TABLE tmp.timeControlError;
DROP TEMPORARY TABLE tmp.wtcToinsert;
DROP TEMPORARY TABLE tmp.workerTimeControl;
END$$
DELIMITER ;

View File

@ -0,0 +1,286 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`workerTimeControl_clockIn`(
vWorkerFk INT,
vTimed DATETIME,
vDirection VARCHAR(10)
)
BEGIN
/**
* Verifica si el empleado puede fichar
* @param vWorkerFk Identificador del trabajador
* @param vTimed valor de la fichada, IF vTimed IS NULL vTimed = NOW
* @param vDirection solo se pueden pasa los valores del campo
* workerTimeControl.direction ENUM('in', 'out', 'middle')
* @return Si todo es correcto, retorna el número de id la tabla workerTimeControl.
* Si hay algún problema, devuelve el mesaje que se debe mostrar al usuario
* Solo retorna el primer problema, en caso de no ocurrir ningún error se añadirá
* fichada a la tabla vn.workerTimeControl
*/
DECLARE vLastIn DATETIME;
DECLARE vLastOut DATETIME;
DECLARE vNextIn DATETIME;
DECLARE vNextOut DATETIME;
DECLARE vNextDirection ENUM('in', 'out');
DECLARE vLastDirection ENUM('in', 'out');
DECLARE vDayMaxTime INTEGER;
DECLARE vDayBreak INT;
DECLARE vShortWeekBreak INT;
DECLARE vLongWeekBreak INT;
DECLARE vWeekScope INT;
DECLARE vMailTo VARCHAR(50) DEFAULT NULL;
DECLARE vUserName VARCHAR(50) DEFAULT NULL;
DECLARE vIsError BOOLEAN DEFAULT FALSE;
DECLARE vErrorMessage VARCHAR(255) DEFAULT NULL;
DECLARE vErrorCode VARCHAR(50);
DECLARE vDated DATE;
DECLARE vIsAllowedToWork VARCHAR(50);
DECLARE vIsManual BOOLEAN DEFAULT TRUE;
DECLARE vMaxWorkShortCycle INT;
DECLARE vMaxWorkLongCycle INT;
DECLARE EXIT HANDLER FOR SQLSTATE '45000'
BEGIN
SELECT CONCAT(u.name, '@verdnatura.es'),
CONCAT(w.firstName, ' ', w.lastName)
INTO vMailTo, vUserName
FROM account.user u
JOIN worker w ON w.bossFk = u.id
WHERE w.id = vWorkerFk;
SELECT `description` INTO vErrorMessage
FROM workerTimeControlError
WHERE `code` = vErrorCode;
IF vErrorMessage IS NULL THEN
SET vErrorMessage = 'Error sin definir';
END IF;
SELECT vErrorMessage `error`;
SELECT CONCAT(vUserName,
' no ha podido fichar por el siguiente problema: ',
vErrorMessage)
INTO vErrorMessage;
CALL mail_insert( vMailTo, vMailTo, 'Error al fichar', vErrorMessage);
END;
IF (vTimed IS NULL) THEN
SET vTimed = util.VN_NOW();
SET vIsManual = FALSE;
END IF;
SET vDated = DATE(vTimed);
SELECT IF(pc.name = 'Conductor +3500kg',
wc.dayBreakDriver,
wc.dayBreak),
wc.shortWeekBreak,
wc.longWeekBreak,
wc.weekScope,
wc.dayMaxTime,
wc.maxWorkShortCycle,
wc.maxWorkLongCycle
INTO vDayBreak,
vShortWeekBreak,
vLongWeekBreak,
vWeekScope,
vDayMaxTime,
vMaxWorkShortCycle,
vMaxWorkLongCycle
FROM business b
JOIN professionalCategory pc
ON pc.id = b.workerBusinessProfessionalCategoryFk
JOIN workerTimeControlConfig wc
WHERE b.workerFk = vWorkerFk
AND vDated BETWEEN b.started AND IFNULL(b.ended, vDated);
-- CONTRATO EN VIGOR
IF vDayBreak IS NULL THEN
SET vErrorCode = 'INACTIVE_BUSINESS';
CALL util.throw(vErrorCode);
END IF;
-- FICHADAS A FUTURO
IF vTimed > util.VN_NOW() + INTERVAL 1 MINUTE THEN
SET vErrorCode = 'IS_NOT_ALLOWED_FUTURE';
CALL util.throw(vErrorCode);
END IF;
-- VERIFICAR SI ESTÁ PERMITIDO TRABAJAR
CALL timeBusiness_calculateByWorker(vWorkerFk, vDated, vDated);
SELECT isAllowedToWork INTO vIsAllowedToWork
FROM tmp.timeBusinessCalculate;
DROP TEMPORARY TABLE tmp.timeBusinessCalculate;
IF NOT vIsAllowedToWork THEN
SET vErrorCode = 'IS_NOT_ALLOWED_WORK';
CALL util.throw(vErrorCode);
END IF;
-- DIRECCION CORRECTA
CALL workerTimeControl_direction(vWorkerFk, vTimed);
IF (SELECT
IF(IF(option1 IN ('inMiddle', 'outMiddle'),
'middle',
option1) <> vDirection
AND IF(option2 IN ('inMiddle', 'outMiddle'),
'middle',
IFNULL(option2, '')) <> vDirection,
TRUE ,
FALSE)
FROM tmp.workerTimeControlDirection
) THEN
SET vIsError = TRUE;
END IF;
DROP TEMPORARY TABLE tmp.workerTimeControlDirection;
IF vIsError THEN
SET vErrorCode = 'WRONG_DIRECTION';
CALL util.throw(vErrorCode);
END IF;
-- FICHADAS IMPARES
SELECT timed INTO vLastIn
FROM workerTimeControl
WHERE userFk = vWorkerFk
AND direction = 'in'
AND timed < vTimed
ORDER BY timed DESC
LIMIT 1;
IF (SELECT IF(vDirection = 'in',
MOD(COUNT(*), 2) ,
IF (vDirection = 'out', NOT MOD(COUNT(*), 2), FALSE))
FROM workerTimeControl
WHERE userFk = vWorkerFk
AND timed BETWEEN vLastIn AND vTimed
) THEN
SET vErrorCode = 'ODD_WORKERTIMECONTROL';
CALL util.throw(vErrorCode);
END IF;
-- DESCANSO DIARIO
SELECT timed INTO vLastOut
FROM workerTimeControl
WHERE userFk = vWorkerFk
AND direction = 'out'
AND timed < vTimed
ORDER BY timed DESC
LIMIT 1;
SELECT timed INTO vNextIn
FROM workerTimeControl
WHERE userFk = vWorkerFk
AND direction = 'in'
AND timed > vTimed
ORDER BY timed ASC
LIMIT 1;
CASE vDirection
WHEN 'in' THEN
IF UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastOut) <= vDayBreak THEN
SET vIsError = TRUE;
END IF;
WHEN 'out' THEN
IF UNIX_TIMESTAMP(vNextIn) - UNIX_TIMESTAMP(vTimed) <= vDayBreak THEN
SET vIsError = TRUE;
END IF;
ELSE BEGIN END;
END CASE;
IF vIsError THEN
SET vErrorCode = 'BREAK_DAY';
CALL util.throw(vErrorCode);
END IF;
IF (vDirection IN('in', 'out')) THEN
-- VERIFICA MAXIMO TIEMPO DESDE ENTRADA HASTA LA SALIDA
SELECT timed INTO vNextOut
FROM workerTimeControl
WHERE userFk = vWorkerFk
AND direction = 'out'
AND timed > vTimed
ORDER BY timed ASC
LIMIT 1;
SELECT direction INTO vNextDirection
FROM workerTimeControl
WHERE userFk = vWorkerFk
AND direction IN('in','out')
AND timed > vTimed
ORDER BY timed ASC
LIMIT 1;
SELECT direction INTO vLastDirection
FROM workerTimeControl
WHERE userFk = vWorkerFk
AND direction IN('in', 'out')
AND timed < vTimed
ORDER BY timed ASC
LIMIT 1;
IF (vDirection ='in'
AND vNextDirection = 'out'
AND UNIX_TIMESTAMP(vNextOut) - UNIX_TIMESTAMP(vTimed) > vDayMaxTime) OR
(vDirection ='out'
AND vLastDirection = 'in'
AND UNIX_TIMESTAMP(vTimed) -UNIX_TIMESTAMP(vLastIn) > vDayMaxTime) THEN
SET vErrorCode = 'DAY_MAX_TIME';
CALL util.throw(vErrorCode);
END IF;
-- VERIFICA DESCANSO SEMANAL
WITH wtc AS(
(SELECT timed
FROM vn.workerTimeControl
WHERE userFk = vWorkerFk
AND direction IN ('in', 'out')
AND timed BETWEEN vTimed - INTERVAL (vWeekScope * 2) SECOND
AND vTimed + INTERVAL (vWeekScope * 2) SECOND )
UNION
(SELECT vTimed)
), wtcGap AS(
SELECT timed,
TIMESTAMPDIFF(SECOND, LAG(timed) OVER (ORDER BY timed), timed) gap
FROM wtc
ORDER BY timed
), wtcBreak AS(
SELECT timed,
IF(IFNULL(gap, 0) > vShortWeekBreak, TRUE, FALSE) hasShortBreak,
IF(IFNULL(gap, 0) > vLongWeekBreak, TRUE, FALSE) hasLongBreak
FROM wtcGap
ORDER BY timed
), wtcBreakCounter AS(
SELECT timed,
SUM(hasShortBreak) OVER (ORDER BY timed) breakCounter ,
LEAD(hasLongBreak) OVER (ORDER BY timed) nextHasLongBreak
FROM wtcBreak
)SELECT TIMESTAMPDIFF(SECOND, MIN(timed), MAX(timed)) > vMaxWorkLongCycle OR
(TIMESTAMPDIFF(SECOND, MIN(timed), MAX(timed))> vMaxWorkShortCycle
AND NOT SUM(IFNULL(nextHasLongBreak, 1)))
hasError INTO vIsError
FROM wtcBreakCounter
GROUP BY breakCounter
HAVING hasError
LIMIT 1;
IF vIsError THEN
SET vErrorCode = 'BREAK_WEEK';
CALL util.throw(vErrorCode);
END IF;
END IF;
-- SE PERMITE FICHAR
INSERT INTO workerTimeControl(userFk, timed, direction, `manual`)
VALUES(vWorkerFk, vTimed, vDirection, vIsManual);
SELECT LAST_INSERT_ID() id;
END$$
DELIMITER ;

View File

@ -0,0 +1 @@
DROP PROCEDURE IF EXISTS `vn`.`workerCreate`;

View File

@ -1,3 +1,43 @@
CREATE SCHEMA IF NOT EXISTS `vn2008`;
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `vn`.`awbVolume`
AS SELECT `d`.`awbFk` AS `awbFk`,
`b`.`stickers` * `i`.`density` * IF(
`p`.`volume` > 0,
`p`.`volume`,
`p`.`width` * `p`.`depth` * IF(`p`.`height` = 0, `i`.`size` + 10, `p`.`height`)
) / (`vc`.`aerealVolumetricDensity` * 1000) AS `volume`,
`b`.`id` AS `buyFk`
FROM (
(
(
(
(
(
(
(
`vn`.`buy` `b`
JOIN `vn`.`item` `i` ON(`b`.`itemFk` = `i`.`id`)
)
JOIN `vn`.`itemType` `it` ON(`i`.`typeFk` = `it`.`id`)
)
JOIN `vn`.`packaging` `p` ON(`p`.`id` = `b`.`packagingFk`)
)
JOIN `vn`.`entry` `e` ON(`b`.`entryFk` = `e`.`id`)
)
JOIN `vn`.`travel` `t` ON(`t`.`id` = `e`.`travelFk`)
)
JOIN `vn`.`duaEntry` `de` ON(`de`.`entryFk` = `e`.`id`)
)
JOIN `vn`.`dua` `d` ON(`d`.`id` = `de`.`duaFk`)
)
JOIN `vn`.`volumeConfig` `vc`
)
WHERE `t`.`shipped` > makedate(year(`util`.`VN_CURDATE`()) - 1, 1);
CREATE OR REPLACE DEFINER=`root`@`localhost` CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER SQL SECURITY DEFINER
VIEW `vn2008`.`Compres` VIEW `vn2008`.`Compres`
@ -108,39 +148,3 @@ FROM (
LEFT JOIN `edi`.`supplier` `s` ON(`e`.`pro` = `s`.`supplier_id`) LEFT JOIN `edi`.`supplier` `s` ON(`e`.`pro` = `s`.`supplier_id`)
); );
CREATE OR REPLACE DEFINER=`root`@`localhost`
SQL SECURITY DEFINER
VIEW `vn`.`awbVolume`
AS SELECT `d`.`awbFk` AS `awbFk`,
`b`.`stickers` * `i`.`density` * IF(
`p`.`volume` > 0,
`p`.`volume`,
`p`.`width` * `p`.`depth` * IF(`p`.`height` = 0, `i`.`size` + 10, `p`.`height`)
) / (`vc`.`aerealVolumetricDensity` * 1000) AS `volume`,
`b`.`id` AS `buyFk`
FROM (
(
(
(
(
(
(
(
`vn`.`buy` `b`
JOIN `vn`.`item` `i` ON(`b`.`itemFk` = `i`.`id`)
)
JOIN `vn`.`itemType` `it` ON(`i`.`typeFk` = `it`.`id`)
)
JOIN `vn`.`packaging` `p` ON(`p`.`id` = `b`.`packagingFk`)
)
JOIN `vn`.`entry` `e` ON(`b`.`entryFk` = `e`.`id`)
)
JOIN `vn`.`travel` `t` ON(`t`.`id` = `e`.`travelFk`)
)
JOIN `vn`.`duaEntry` `de` ON(`de`.`entryFk` = `e`.`id`)
)
JOIN `vn`.`dua` `d` ON(`d`.`id` = `de`.`duaFk`)
)
JOIN `vn`.`volumeConfig` `vc`
)
WHERE `t`.`shipped` > makedate(year(`util`.`VN_CURDATE`()) - 1, 1);

View File

View File

@ -0,0 +1,4 @@
UPDATE `salix`.`ACL`
SET `property` = 'state',
`model` = 'Ticket'
WHERE `property` = 'changeState';

View File

@ -0,0 +1,98 @@
-- Place your SQL code here
ALTER TABLE `vn`.`productionConfig` ADD shortageAddressFk int(11) COMMENT 'Consignatario por defecto para añadir un item de alta';
ALTER TABLE `vn`.`productionConfig` ADD CONSTRAINT productionConfig_FK FOREIGN KEY (shortageAddressFk) REFERENCES vn.address(id) ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE `vn`.`sale` MODIFY COLUMN originalQuantity double(9,1) DEFAULT NULL NULL COMMENT 'Se utiliza para notificar a través de rocket los cambios de quantity';
INSERT INTO `salix`.`ACL` ( model, property, accessType, permission, principalType, principalId) VALUES( 'AddressShortage', '*', 'READ', 'ALLOW', 'ROLE', 'production');
-- vn.addressShortage definition
CREATE TABLE `vn`.`addressShortage` (
`addressFk` int(11) NOT NULL,
PRIMARY KEY (`addressFk`),
CONSTRAINT `addressShortage_FK` FOREIGN KEY (`addressFk`) REFERENCES `address` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_setVisibleDiscard`(
vItemFk INT,
vWarehouseFk INT,
vQuantity INT,
vAddressFk INT)
BEGIN
/**
* Procedimiento para dar dar de baja/alta un item, si vAddressFk es NULL se entiende que se da de alta y se toma el addressFk de la configuración
*
* @param vItemFk Identificador del ítem
* @param vWarehouseFk id del warehouse
* @param vQuantity a dar de alta/baja
* @param vAddressFk id address
*/
DECLARE vTicketFk INT;
DECLARE vClientFk INT;
DECLARE vDefaultCompanyFk INT;
DECLARE vCalc INT;
DECLARE vAddressShortage INT;
SELECT barcodeToItem(vItemFk) INTO vItemFk;
SELECT DEFAULT(companyFk) INTO vDefaultCompanyFk
FROM vn.ticket LIMIT 1;
IF vAddressFk IS NULL THEN
SELECT pc.shortageAddressFk INTO vAddressShortage
FROM productionConfig pc ;
ELSE
SET vAddressShortage = vAddressFk;
END IF;
SELECT a.clientFk INTO vClientFk
FROM address a
WHERE a.id = vAddressFk;
SELECT t.id INTO vTicketFk
FROM ticket t
JOIN address a ON a.id = t.addressFk
JOIN ticketState ts ON ts.ticketFk = t.id
WHERE t.warehouseFk = vWarehouseFk
AND a.id = vAddressShortage
AND DATE(t.shipped) = util.VN_CURDATE()
AND ts.code = 'DELIVERED'
LIMIT 1;
CALL cache.visible_refresh(vCalc, TRUE, vWarehouseFk);
IF vTicketFk IS NULL THEN
CALL ticket_add(
vClientFk,
util.VN_CURDATE(),
vWarehouseFk,
vDefaultCompanyFk,
vAddressFk,
NULL,
NULL,
util.VN_CURDATE(),
account.myUser_getId(),
FALSE,
vTicketFk);
END IF;
INSERT INTO sale(ticketFk, itemFk, concept, quantity)
SELECT vTicketFk,
vItemFk,
CONCAT(longName,' ', worker_getCode(), ' ', LEFT(CAST(util.VN_NOW() AS TIME),5)),
vQuantity
FROM item
WHERE id = vItemFk;
UPDATE cache.visible
SET visible = visible - vQuantity
WHERE calc_id = vCalc
AND item_id = vItemFk;
END$$
DELIMITER ;

View File

@ -21,11 +21,11 @@ DELETE FROM `salix`.`ACL`
'getSummary' 'getSummary'
); );
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`) INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`)
VALUES ('Claim','filter','READ','ALLOW','ROLE','claimViewer'); VALUES ('Claim','filter','READ','ALLOW','ROLE','claimViewer');
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`) INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`)
VALUES ('Claim','find','READ','ALLOW','ROLE','claimViewer'); VALUES ('Claim','find','READ','ALLOW','ROLE','claimViewer');
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`) INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`)
VALUES ('Claim','findById','READ','ALLOW','ROLE','claimViewer'); VALUES ('Claim','findById','READ','ALLOW','ROLE','claimViewer');
INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`) INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`)
VALUES ('Claim','getSummary','READ','ALLOW','ROLE','claimViewer'); VALUES ('Claim','getSummary','READ','ALLOW','ROLE','claimViewer');

View File

@ -0,0 +1,95 @@
ALTER TABLE `vn`.`client` MODIFY COLUMN `credit` decimal(10,2) unsigned DEFAULT 0.00 NOT NULL;
DELETE FROM `salix`.`ACL` WHERE `model` = 'Client' AND `property` = 'create';
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`client_beforeUpdate`
BEFORE UPDATE ON `client`
FOR EACH ROW
BEGIN
DECLARE vText VARCHAR(255) DEFAULT NULL;
DECLARE vPayMethodFk INT;
SET NEW.editorFk = account.myUser_getId();
IF NOT(NEW.credit <=> OLD.credit) THEN
INSERT INTO clientCredit
SET clientFk = NEW.id,
amount = NEW.credit,
workerFk = NEW.editorFk;
END IF;
-- Comprueba que el formato de los teléfonos es válido
IF !(NEW.phone <=> OLD.phone) AND (NEW.phone <> '') THEN
CALL pbx.phone_isValid(NEW.phone);
END IF;
IF !(NEW.mobile <=> OLD.mobile) AND (NEW.mobile <> '')THEN
CALL pbx.phone_isValid(NEW.mobile);
END IF;
SELECT id INTO vPayMethodFk
FROM vn.payMethod
WHERE code = 'bankDraft';
IF NEW.payMethodFk = vPayMethodFk AND NEW.dueDay = 0 THEN
SET NEW.dueDay = 5;
END IF;
-- Avisar al comercial si ha llegado la documentación sepa/core
IF NEW.hasSepaVnl AND !OLD.hasSepaVnl THEN
SET vText = 'Sepa de VNL';
END IF;
IF NEW.hasCoreVnl AND !OLD.hasCoreVnl THEN
SET vText = 'Core de VNL';
END IF;
IF vText IS NOT NULL
THEN
INSERT INTO mail(receiver, replyTo, `subject`, body)
SELECT
CONCAT(IF(ac.id,u.name, 'jgallego'), '@verdnatura.es'),
'administracion@verdnatura.es',
CONCAT('Cliente ', NEW.id),
CONCAT('Recibida la documentación: ', vText)
FROM worker w
LEFT JOIN account.user u ON w.id = u.id AND u.active
LEFT JOIN account.account ac ON ac.id = u.id
WHERE w.id = NEW.salesPersonFk;
END IF;
IF NEW.salespersonFk IS NULL AND OLD.salespersonFk IS NOT NULL THEN
IF (SELECT COUNT(clientFk)
FROM clientProtected
WHERE clientFk = NEW.id
) > 0 THEN
CALL util.throw("HAS_CLIENT_PROTECTED");
END IF;
END IF;
IF !(NEW.salesPersonFk <=> OLD.salesPersonFk) THEN
SET NEW.lastSalesPersonFk = IFNULL(NEW.salesPersonFk, OLD.salesPersonFk);
END IF;
IF !(NEW.businessTypeFk <=> OLD.businessTypeFk) AND (NEW.businessTypeFk = 'individual' OR OLD.businessTypeFk = 'individual') THEN
SET NEW.isTaxDataChecked = 0;
END IF;
END$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`client_AfterInsert`
AFTER INSERT ON `client`
FOR EACH ROW
BEGIN
IF NEW.credit IS NOT NULL AND NEW.credit THEN
INSERT INTO clientCredit
SET clientFk = NEW.id,
workerFk = NEW.editorFk,
amount = NEW.credit;
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,13 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`expeditionState_BeforeInsert`
BEFORE INSERT ON `expeditionState`
FOR EACH ROW
BEGIN
SET NEW.userFk = IFNULL(NEW.userFk, account.myUser_getId());
END$$
DELIMITER ;

View File

@ -0,0 +1,55 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_setState`(
vSelf INT,
vStateCode VARCHAR(255) COLLATE utf8_general_ci
)
BEGIN
/**
* Modifica el estado de un ticket si se cumplen las condiciones necesarias.
*
* @param vSelf el id del ticket
* @param vStateCode estado a modificar del ticket
*/
DECLARE vticketAlertLevel INT;
DECLARE vTicketStateCode VARCHAR(255);
DECLARE vCanChangeState BOOL;
DECLARE vPackedAlertLevel INT;
DECLARE vZoneFk INT;
SELECT s.alertLevel, s.`code`, t.zoneFk
INTO vticketAlertLevel, vTicketStateCode, vZoneFk
FROM state s
JOIN ticketTracking tt ON tt.stateFk = s.id
JOIN ticket t ON t.id = tt.ticketFk
WHERE tt.ticketFk = vSelf
ORDER BY tt.created DESC
LIMIT 1;
SELECT id INTO vPackedAlertLevel FROM alertLevel WHERE code = 'PACKED';
IF vStateCode = 'OK' AND vZoneFk IS NULL THEN
CALL util.throw('ASSIGN_ZONE_FIRST');
END IF;
SET vCanChangeState = (
vStateCode <> 'ON_CHECKING' OR
vticketAlertLevel < vPackedAlertLevel
)AND NOT (
vTicketStateCode IN ('CHECKED', 'CHECKING')
AND vStateCode IN ('PREPARED', 'ON_PREPARATION')
);
IF vCanChangeState THEN
INSERT INTO ticketTracking (stateFk, ticketFk, workerFk)
SELECT id, vSelf, account.myUser_getId()
FROM state
WHERE `code` = vStateCode COLLATE utf8_unicode_ci;
IF vStateCode = 'PACKED' THEN
CALL ticket_doCmr(vSelf);
END IF;
ELSE
CALL util.throw('INCORRECT_TICKET_STATE');
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,6 @@
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
VALUES
('CplusRectificationType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('CplusInvoiceType477', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceCorrectionType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('InvoiceOut', 'transferInvoice', 'WRITE', 'ALLOW', 'ROLE', 'administrative');

View File

View File

@ -470,22 +470,22 @@ CREATE TEMPORARY TABLE tmp.address
WHERE `defaultAddressFk` IS NULL; WHERE `defaultAddressFk` IS NULL;
DROP TEMPORARY TABLE tmp.address; DROP TEMPORARY TABLE tmp.address;
INSERT INTO `vn`.`clientCredit`(`id`, `clientFk`, `workerFk`, `amount`, `created`) INSERT INTO `vn`.`clientCredit`(`clientFk`, `workerFk`, `amount`, `created`)
VALUES VALUES
(1 , 1101, 5, 300, DATE_ADD(util.VN_CURDATE(), INTERVAL -11 MONTH)), (1101, 5, 300, DATE_ADD(util.VN_CURDATE(), INTERVAL -11 MONTH)),
(2 , 1101, 5, 900, DATE_ADD(util.VN_CURDATE(), INTERVAL -10 MONTH)), (1101, 5, 900, DATE_ADD(util.VN_CURDATE(), INTERVAL -10 MONTH)),
(3 , 1101, 5, 800, DATE_ADD(util.VN_CURDATE(), INTERVAL -9 MONTH)), (1101, 5, 800, DATE_ADD(util.VN_CURDATE(), INTERVAL -9 MONTH)),
(4 , 1101, 5, 700, DATE_ADD(util.VN_CURDATE(), INTERVAL -8 MONTH)), (1101, 5, 700, DATE_ADD(util.VN_CURDATE(), INTERVAL -8 MONTH)),
(5 , 1101, 5, 600, DATE_ADD(util.VN_CURDATE(), INTERVAL -7 MONTH)), (1101, 5, 600, DATE_ADD(util.VN_CURDATE(), INTERVAL -7 MONTH)),
(6 , 1101, 5, 500, DATE_ADD(util.VN_CURDATE(), INTERVAL -6 MONTH)), (1101, 5, 500, DATE_ADD(util.VN_CURDATE(), INTERVAL -6 MONTH)),
(7 , 1101, 5, 400, DATE_ADD(util.VN_CURDATE(), INTERVAL -5 MONTH)), (1101, 5, 400, DATE_ADD(util.VN_CURDATE(), INTERVAL -5 MONTH)),
(8 , 1101, 9, 300, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH)), (1101, 9, 300, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH)),
(9 , 1101, 9, 200, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH)), (1101, 9, 200, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH)),
(10, 1101, 9, 100, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH)), (1101, 9, 100, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH)),
(11, 1101, 9, 50 , DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)), (1101, 9, 50 , DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)),
(12, 1102, 9, 800, util.VN_CURDATE()), (1102, 9, 800, util.VN_CURDATE()),
(14, 1104, 9, 90 , util.VN_CURDATE()), (1104, 9, 90 , util.VN_CURDATE()),
(15, 1105, 9, 90 , util.VN_CURDATE()); (1105, 9, 90 , util.VN_CURDATE());
INSERT INTO `vn`.`clientCreditLimit`(`id`, `maxAmount`, `roleFk`) INSERT INTO `vn`.`clientCreditLimit`(`id`, `maxAmount`, `roleFk`)
VALUES VALUES
@ -604,7 +604,7 @@ INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaF
INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`) INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`)
VALUES VALUES
(1, 'T', 1014.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (1, 'T', 1026.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
(2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
(3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
(4, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (4, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0),
@ -2003,6 +2003,10 @@ UPDATE `vn`.`business` b
SET b.`departmentFk` = 43 SET b.`departmentFk` = 43
WHERE b.id IN(18, 19); WHERE b.id IN(18, 19);
UPDATE `vn`.`business` b
SET b.`started` = b.`started` - INTERVAL 100 DAY
WHERE b.id = 1107;
INSERT INTO `vn`.`workCenterHoliday` (`workCenterFk`, `days`, `year`) INSERT INTO `vn`.`workCenterHoliday` (`workCenterFk`, `days`, `year`)
VALUES VALUES
('1', '27.5', YEAR(util.VN_CURDATE())), ('1', '27.5', YEAR(util.VN_CURDATE())),
@ -2051,22 +2055,22 @@ INSERT INTO `vn`.`absenceType` (`id`, `name`, `rgb`, `code`, `holidayEntitlement
INSERT INTO `vn`.`calendar` (`businessFk`, `dayOffTypeFk`, `dated`) INSERT INTO `vn`.`calendar` (`businessFk`, `dayOffTypeFk`, `dated`)
VALUES VALUES
(1, 6, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, DATE_ADD(util.VN_CURDATE(), INTERVAL -10 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 10 DAY))), (1, 6, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, util.VN_CURDATE() - INTERVAL 10 DAY, util.VN_CURDATE() + INTERVAL 10 DAY)),
(1106, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, DATE_ADD(util.VN_CURDATE(), INTERVAL -10 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 10 DAY))), (1106, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, util.VN_CURDATE() - INTERVAL 10 DAY, util.VN_CURDATE() + INTERVAL 10 DAY)),
(1106, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, DATE_ADD(util.VN_CURDATE(), INTERVAL -11 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 11 DAY))), (1106, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, util.VN_CURDATE() - INTERVAL 11 DAY, util.VN_CURDATE() + INTERVAL 11 DAY)),
(1106, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, DATE_ADD(util.VN_CURDATE(), INTERVAL -12 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 12 DAY))), (1106, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, util.VN_CURDATE() - INTERVAL 12 DAY, util.VN_CURDATE() + INTERVAL 12 DAY)),
(1106, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, DATE_ADD(util.VN_CURDATE(), INTERVAL -20 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 20 DAY))), (1106, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, util.VN_CURDATE() - INTERVAL 20 DAY, util.VN_CURDATE() + INTERVAL 20 DAY)),
(1106, 2, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, DATE_ADD(util.VN_CURDATE(), INTERVAL -13 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 8 DAY))), (1106, 2, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, util.VN_CURDATE() - INTERVAL 13 DAY, util.VN_CURDATE() + INTERVAL 8 DAY)),
(1106, 1, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, DATE_ADD(util.VN_CURDATE(), INTERVAL -14 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 9 DAY))), (1106, 1, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, util.VN_CURDATE() - INTERVAL 14 DAY, util.VN_CURDATE() + INTERVAL 9 DAY)),
(1106, 2, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, DATE_ADD(util.VN_CURDATE(), INTERVAL -15 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 7 DAY))), (1106, 2, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, util.VN_CURDATE() - INTERVAL 15 DAY, util.VN_CURDATE() + INTERVAL 7 DAY)),
(1107, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, DATE_ADD(util.VN_CURDATE(), INTERVAL -10 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 10 DAY))), (1107, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, util.VN_CURDATE() - INTERVAL 10 DAY, util.VN_CURDATE() + INTERVAL 10 DAY)),
(1107, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, DATE_ADD(util.VN_CURDATE(), INTERVAL -11 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 11 DAY))), (1107, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, util.VN_CURDATE() - INTERVAL 11 DAY, util.VN_CURDATE() + INTERVAL 11 DAY)),
(1107, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, DATE_ADD(util.VN_CURDATE(), INTERVAL -12 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 12 DAY))), (1107, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, util.VN_CURDATE() - INTERVAL 12 DAY, util.VN_CURDATE() + INTERVAL 12 DAY)),
(1107, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, DATE_ADD(util.VN_CURDATE(), INTERVAL -20 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 20 DAY))), (1107, 1, IF(MONTH(util.VN_CURDATE()) = 12 AND DAY(util.VN_CURDATE()) > 10, util.VN_CURDATE() - INTERVAL 20 DAY, util.VN_CURDATE() + INTERVAL 20 DAY)),
(1107, 2, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, DATE_ADD(util.VN_CURDATE(), INTERVAL -13 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 8 DAY))), (1107, 2, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, util.VN_CURDATE() - INTERVAL 13 DAY, util.VN_CURDATE() + INTERVAL 8 DAY)),
(1107, 1, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, DATE_ADD(util.VN_CURDATE(), INTERVAL -14 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 9 DAY))), (1107, 1, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, util.VN_CURDATE() - INTERVAL 14 DAY, util.VN_CURDATE() + INTERVAL 9 DAY)),
(1107, 2, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, DATE_ADD(util.VN_CURDATE(), INTERVAL -15 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL 7 DAY))), (1107, 2, IF(MONTH(util.VN_CURDATE()) >= 1 AND DAY(util.VN_CURDATE()) > 20, util.VN_CURDATE() - INTERVAL 15 DAY, util.VN_CURDATE() + INTERVAL 7 DAY)),
(1107, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL - 16 DAY)); (1107, 2, util.VN_CURDATE() - INTERVAL 16 DAY);
INSERT INTO `vn`.`smsConfig` (`id`, `uri`, `title`, `apiKey`) INSERT INTO `vn`.`smsConfig` (`id`, `uri`, `title`, `apiKey`)
VALUES VALUES
@ -2754,9 +2758,9 @@ INSERT INTO `vn`.`sectorCollectionSaleGroup` (`sectorCollectionFk`, `saleGroupFk
VALUES VALUES
(1, 1); (1, 1);
INSERT INTO `vn`.`workerTimeControlConfig` (`id`, `dayBreak`, `dayBreakDriver`, `shortWeekBreak`, `longWeekBreak`, `weekScope`, `mailPass`, `mailHost`, `mailSuccessFolder`, `mailErrorFolder`, `mailUser`, `minHoursToBreak`, `breakHours`, `hoursCompleteWeek`, `startNightlyHours`, `endNightlyHours`, `maxTimePerDay`, `breakTime`, `timeToBreakTime`, `dayMaxTime`, `shortWeekDays`, `longWeekDays`, `teleworkingStart`, `teleworkingStartBreakTime`) INSERT INTO `vn`.`workerTimeControlConfig` (`id`, `dayBreak`, `dayBreakDriver`, `shortWeekBreak`, `longWeekBreak`, `weekScope`, `mailPass`, `mailHost`, `mailSuccessFolder`, `mailErrorFolder`, `mailUser`, `minHoursToBreak`, `breakHours`, `hoursCompleteWeek`, `startNightlyHours`, `endNightlyHours`, `maxTimePerDay`, `breakTime`, `timeToBreakTime`, `dayMaxTime`, `shortWeekDays`, `longWeekDays`, `teleworkingStart`, `teleworkingStartBreakTime`, `maxTimeToBreak`, `maxWorkShortCycle`, `maxWorkLongCycle`)
VALUES VALUES
(1, 43200, 32400, 129600, 259200, 604800, '', '', 'Leidos.exito', 'Leidos.error', 'timeControl', 5.33, 0.33, 40, '22:00:00', '06:00:00', 57600, 1200, 18000, 57600, 6, 13, 28800, 32400); (1, 43200, 32400, 129600, 259200, 1080000, '', 'imap.verdnatura.es', 'Leidos.exito', 'Leidos.error', 'timeControl', 5.00, 0.33, 40, '22:00:00', '06:00:00', 72000, 1200, 18000, 72000, 6, 13, 28800, 32400, 3600, 561600, 950400);
INSERT INTO `vn`.`host` (`id`, `code`, `description`, `warehouseFk`, `bankFk`) INSERT INTO `vn`.`host` (`id`, `code`, `description`, `warehouseFk`, `bankFk`)
VALUES VALUES
@ -2977,3 +2981,9 @@ INSERT INTO vn.XDiario (id, ASIEN, FECHA, SUBCTA, CONTRA, CONCEPTO, EURODEBE, EU
INSERT INTO `vn`.`mistakeType` (`id`, `description`) INSERT INTO `vn`.`mistakeType` (`id`, `description`)
VALUES VALUES
(1, 'Incorrect quantity'); (1, 'Incorrect quantity');
INSERT INTO `vn`.`invoiceCorrectionType` (`id`, `description`)
VALUES
(1, 'Error in VAT calculation'),
(2, 'Error in sales details'),
(3, 'Error in customer data');

View File

@ -53,7 +53,8 @@ describe('ticket ticketCalculateClon()', () => {
expect(result[orderIndex][0].ticketFk).toBeGreaterThan(newestTicketIdInFixtures); expect(result[orderIndex][0].ticketFk).toBeGreaterThan(newestTicketIdInFixtures);
}); });
it('should add the ticket to the order containing the original ticket and generate landed value if it was null', async() => { it('should add the ticket to the order containing the original ' +
'ticket and generate landed value if it was null', async() => {
let stmts = []; let stmts = [];
let stmt; let stmt;

View File

@ -1,91 +0,0 @@
const app = require('vn-loopback/server/server');
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
describe('timeControl_calculateByUser()', () => {
it(`should return today's worked hours`, async() => {
let start = Date.vnNew();
start.setHours(0, 0, 0, 0);
start.setDate(start.getDate() - 1);
let end = Date.vnNew();
end.setHours(0, 0, 0, 0);
end.setDate(end.getDate() + 1);
let stmts = [];
let stmt;
let params = {
workerID: 1106,
start: start,
end: end
};
stmt = new ParameterizedSQL('CALL vn.timeControl_calculateByUser(?, ?, ?)', [
params.workerID,
params.start,
params.end
]);
stmts.push(stmt);
let tableIndex = stmts.push('SELECT * FROM tmp.timeControlCalculate') - 1;
let sql = ParameterizedSQL.join(stmts, ';');
let result = await app.models.Ticket.rawStmt(sql);
let [timeControlCalculateTable] = result[tableIndex];
expect(timeControlCalculateTable.timeWorkSeconds).toEqual(28200);
});
// #2261
xit(`should return the worked hours between last sunday and monday`, async() => {
let lastSunday = Date.vnNew();
let daysSinceSunday = lastSunday.getDay();
if (daysSinceSunday === 0) // this means today is sunday but you need the previous sunday :)
daysSinceSunday = 7;
lastSunday.setHours(23, 0, 0, 0);
lastSunday.setDate(lastSunday.getDate() - daysSinceSunday);
let monday = Date.vnNew();
let daysSinceMonday = daysSinceSunday - 1; // aiming for monday (today could be monday)
monday.setHours(7, 0, 0, 0);
monday.setDate(monday.getDate() - daysSinceMonday);
let stmts = [];
let stmt;
stmts.push('START TRANSACTION');
const workerID = 1108;
stmt = new ParameterizedSQL(`
INSERT INTO vn.workerTimeControl(userFk, timed, manual, direction)
VALUES
(?, ?, 1, 'in'),
(?, ?, 1, 'out')
`, [
workerID,
lastSunday,
workerID,
monday
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.timeControl_calculateByUser(?, ?, ?)', [
workerID,
lastSunday,
monday
]);
stmts.push(stmt);
let tableIndex = stmts.push('SELECT * FROM tmp.timeControlCalculate') - 1;
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
let result = await app.models.Ticket.rawStmt(sql);
let [timeControlCalculateTable] = result[tableIndex];
expect(timeControlCalculateTable.timeWorkSeconds).toEqual(30000);
});
});

Some files were not shown because too many files have changed in this diff Show More