2022-10-31 06:34:34 +00:00
const ParameterizedSQL = require ( 'loopback-connector' ) . ParameterizedSQL ;
module . exports = Self => {
Self . remoteMethodCtx ( 'sendMail' , {
description : ` Send an email with the hours booked to the employees who telecommuting.
It also inserts booked hours in cases where the employee is telecommuting ` ,
accessType : 'WRITE' ,
accepts : [ {
arg : 'workerId' ,
type : 'number' ,
description : 'The worker id'
} ,
{
arg : 'week' ,
2022-10-31 12:00:32 +00:00
type : 'number'
2022-10-31 06:34:34 +00:00
} ,
{
arg : 'year' ,
2022-10-31 12:00:32 +00:00
type : 'number'
2022-10-31 06:34:34 +00:00
} ] ,
returns : [ {
type : 'Object' ,
root : true
} ] ,
http : {
path : ` /sendMail ` ,
verb : 'POST'
}
} ) ;
Self . sendMail = async ( ctx , options ) => {
const models = Self . app . models ;
2022-11-02 13:22:18 +00:00
const conn = Self . dataSource . connector ;
2022-10-31 06:34:34 +00:00
const args = ctx . args ;
2022-11-02 13:22:18 +00:00
let tx ;
2023-06-20 06:16:36 +00:00
const myOptions = { } ;
2022-10-31 06:34:34 +00:00
if ( typeof options == 'object' )
Object . assign ( myOptions , options ) ;
2022-11-02 13:22:18 +00:00
const stmts = [ ] ;
let stmt ;
2022-10-31 12:00:32 +00:00
2023-01-18 13:23:05 +00:00
if ( ! args . week || ! args . year ) {
2023-01-23 07:07:14 +00:00
const from = Date . vnNew ( ) ;
const to = Date . vnNew ( ) ;
2022-10-31 12:00:32 +00:00
2023-01-18 13:23:05 +00:00
const time = await models . Time . findOne ( {
where : {
dated : { between : [ from . setDate ( from . getDate ( ) - 10 ) , to . setDate ( to . getDate ( ) - 4 ) ] }
} ,
order : 'week ASC'
} , myOptions ) ;
2022-10-31 12:00:32 +00:00
2023-01-18 13:23:05 +00:00
args . week = time . week ;
args . year = time . year ;
}
2022-10-31 12:00:32 +00:00
2023-01-18 13:23:05 +00:00
const started = getStartDateOfWeekNumber ( args . week , args . year ) ;
started . setHours ( 0 , 0 , 0 , 0 ) ;
const ended = new Date ( started ) ;
ended . setDate ( started . getDate ( ) + 6 ) ;
ended . setHours ( 23 , 59 , 59 , 999 ) ;
stmts . push ( 'DROP TEMPORARY TABLE IF EXISTS tmp.timeControlCalculate' ) ;
stmts . push ( 'DROP TEMPORARY TABLE IF EXISTS tmp.timeBusinessCalculate' ) ;
if ( args . workerId ) {
await models . WorkerTimeControl . destroyAll ( {
userFk : args . workerId ,
timed : { between : [ started , ended ] } ,
isSendMail : true
} , myOptions ) ;
const where = {
workerFk : args . workerId ,
year : args . year ,
week : args . week
} ;
await models . WorkerTimeControlMail . updateAll ( where , {
2023-01-23 07:07:14 +00:00
updated : Date . vnNew ( ) , state : 'SENDED'
2023-01-18 13:23:05 +00:00
} , myOptions ) ;
2023-04-05 13:14:42 +00:00
stmt = new ParameterizedSQL ( 'DROP TEMPORARY TABLE IF EXISTS tmp.`user`' ) ;
2023-01-18 13:23:05 +00:00
stmts . push ( stmt ) ;
2023-04-06 06:54:12 +00:00
stmt = new ParameterizedSQL ( 'CREATE TEMPORARY TABLE tmp.`user` SELECT id userFk FROM account.user WHERE id = ?' , [ args . workerId ] ) ;
2023-01-18 13:23:05 +00:00
stmts . push ( stmt ) ;
} else {
await models . WorkerTimeControl . destroyAll ( {
timed : { between : [ started , ended ] } ,
isSendMail : true
} , myOptions ) ;
const where = {
year : args . year ,
week : args . week
} ;
await models . WorkerTimeControlMail . updateAll ( where , {
2023-01-23 07:07:14 +00:00
updated : Date . vnNew ( ) , state : 'SENDED'
2023-01-18 13:23:05 +00:00
} , myOptions ) ;
2023-04-05 13:14:42 +00:00
stmt = new ParameterizedSQL ( 'DROP TEMPORARY TABLE IF EXISTS tmp.`user`' ) ;
2023-01-18 13:23:05 +00:00
stmts . push ( stmt ) ;
2023-04-05 13:14:42 +00:00
stmt = new ParameterizedSQL ( 'CREATE TEMPORARY TABLE IF NOT EXISTS tmp.`user` SELECT userFk FROM vn.worker w JOIN account.`user` u ON u.id = w.userFk WHERE userFk IS NOT NULL' ) ;
2023-01-18 13:23:05 +00:00
stmts . push ( stmt ) ;
}
2022-10-31 06:34:34 +00:00
2023-04-05 13:14:42 +00:00
stmt = new ParameterizedSQL (
` CALL vn.timeControl_calculate(?, ?)
` , [started, ended]);
stmts . push ( stmt ) ;
stmt = new ParameterizedSQL (
2023-04-06 06:54:12 +00:00
` CALL vn.timeBusiness_calculate(?, ?)
2023-04-05 13:14:42 +00:00
` , [started, ended]);
stmts . push ( stmt ) ;
stmt = new ParameterizedSQL (
2023-04-06 06:54:12 +00:00
` CALL vn.timeControl_getError(?, ?)
2023-04-05 13:14:42 +00:00
` , [started, ended]);
stmts . push ( stmt ) ;
2023-04-06 06:54:12 +00:00
stmt = new ParameterizedSQL ( ` INSERT INTO mail (receiver, subject, body)
SELECT CONCAT ( u . name , '@verdnatura.es' ) ,
CONCAT ( 'Error registro de horas semana ' , ? , ' año ' , ? ) ,
CONCAT ( 'No se ha podido enviar el registro de horas al empleado/s: ' , GROUP _CONCAT ( DISTINCT CONCAT ( '<br>' , w . id , ' ' , w . firstName , ' ' , w . lastName ) ) )
FROM tmp . timeControlError tce
JOIN vn . workerTimeControl wtc ON wtc . id = tce . id
JOIN worker w ON w . id = wtc . userFK
JOIN account . user u ON u . id = w . bossFk
GROUP BY w . bossFk ` , [args.week, args.year]);
stmts . push ( stmt ) ;
2023-01-18 13:23:05 +00:00
stmt = new ParameterizedSQL ( `
2022-10-31 13:48:37 +00:00
SELECT CONCAT ( u . name , '@verdnatura.es' ) receiver ,
2022-10-31 12:30:08 +00:00
u . id workerFk ,
tb . dated ,
tb . timeWorkDecimal ,
tb . timeWorkSexagesimal timeWorkSexagesimal ,
tb . timeTable ,
tc . timeWorkDecimal timeWorkedDecimal ,
tc . timeWorkSexagesimal timeWorkedSexagesimal ,
tb . type ,
tb . businessFk ,
tb . permissionRate ,
d . isTeleworking
FROM tmp . timeBusinessCalculate tb
2022-11-23 09:09:09 +00:00
JOIN account . user u ON u . id = tb . userFk
2022-10-31 12:30:08 +00:00
JOIN department d ON d . id = tb . departmentFk
JOIN business b ON b . id = tb . businessFk
LEFT JOIN tmp . timeControlCalculate tc ON tc . userFk = tb . userFk AND tc . dated = tb . dated
LEFT JOIN worker w ON w . id = u . id
2023-04-05 13:14:42 +00:00
LEFT JOIN (
SELECT DISTINCT wtc . userFk
FROM tmp . timeControlError tce
JOIN vn . workerTimeControl wtc ON wtc . id = tce . id
) sub ON sub . userFk = tb . userFk
WHERE sub . userFK IS NULL
AND IFNULL ( ? , u . id ) = u . id
2022-10-31 12:30:08 +00:00
AND b . companyCodeFk = 'VNL'
AND w . businessFk
2023-03-29 09:27:48 +00:00
AND d . isTeleworking
2022-10-31 12:30:08 +00:00
ORDER BY u . id , tb . dated
` , [args.workerId]);
2023-01-18 13:23:05 +00:00
const index = stmts . push ( stmt ) - 1 ;
2022-10-31 06:34:34 +00:00
2023-01-18 13:23:05 +00:00
stmts . push ( 'DROP TEMPORARY TABLE tmp.timeControlCalculate' ) ;
stmts . push ( 'DROP TEMPORARY TABLE tmp.timeBusinessCalculate' ) ;
2022-10-31 06:34:34 +00:00
2023-01-18 13:23:05 +00:00
const sql = ParameterizedSQL . join ( stmts , ';' ) ;
const days = await conn . executeStmt ( sql , myOptions ) ;
2022-11-02 13:22:18 +00:00
2023-01-18 13:23:05 +00:00
let previousWorkerFk = days [ index ] [ 0 ] . workerFk ;
let previousReceiver = days [ index ] [ 0 ] . receiver ;
2022-10-31 06:34:34 +00:00
2023-01-18 13:23:05 +00:00
const workerTimeControlConfig = await models . WorkerTimeControlConfig . findOne ( null , myOptions ) ;
2022-11-07 11:21:14 +00:00
2023-01-18 13:23:05 +00:00
for ( let day of days [ index ] ) {
2023-01-19 07:54:26 +00:00
if ( ! myOptions . transaction ) {
tx = await Self . beginTransaction ( { } ) ;
myOptions . transaction = tx ;
}
2023-01-18 13:23:05 +00:00
try {
2022-11-02 13:22:18 +00:00
workerFk = day . workerFk ;
if ( day . timeWorkDecimal > 0 && day . timeWorkedDecimal == null
2023-01-18 12:05:02 +00:00
&& ( day . permissionRate == null ? true : day . permissionRate ) ) {
2022-11-02 13:22:18 +00:00
if ( day . timeTable == null ) {
const timed = new Date ( day . dated ) ;
2022-10-31 06:34:34 +00:00
await models . WorkerTimeControl . create ( {
userFk : day . workerFk ,
2023-01-12 07:50:03 +00:00
timed : timed . setHours ( workerTimeControlConfig . teleworkingStart / 3600 ) ,
2022-10-31 06:34:34 +00:00
manual : true ,
2022-11-02 13:22:18 +00:00
direction : 'in' ,
2022-10-31 06:34:34 +00:00
isSendMail : true
} , myOptions ) ;
2022-11-07 11:21:14 +00:00
if ( day . timeWorkDecimal >= workerTimeControlConfig . timeToBreakTime / 3600 ) {
2022-10-31 06:34:34 +00:00
await models . WorkerTimeControl . create ( {
userFk : day . workerFk ,
2023-01-12 07:50:03 +00:00
timed : timed . setHours ( workerTimeControlConfig . teleworkingStartBreakTime / 3600 ) ,
2022-10-31 06:34:34 +00:00
manual : true ,
2022-11-02 13:22:18 +00:00
direction : 'middle' ,
2022-10-31 06:34:34 +00:00
isSendMail : true
} , myOptions ) ;
await models . WorkerTimeControl . create ( {
userFk : day . workerFk ,
2023-01-12 07:50:03 +00:00
timed : timed . setHours (
workerTimeControlConfig . teleworkingStartBreakTime / 3600 ,
workerTimeControlConfig . breakTime / 60
) ,
2022-10-31 06:34:34 +00:00
manual : true ,
2022-11-02 13:22:18 +00:00
direction : 'middle' ,
2022-10-31 06:34:34 +00:00
isSendMail : true
} , myOptions ) ;
2022-11-02 13:22:18 +00:00
}
2022-10-31 06:34:34 +00:00
2022-11-02 13:22:18 +00:00
const [ hoursWork , minutesWork , secondsWork ] = getTime ( day . timeWorkSexagesimal ) ;
await models . WorkerTimeControl . create ( {
userFk : day . workerFk ,
2023-01-12 07:50:03 +00:00
timed : timed . setHours (
workerTimeControlConfig . teleworkingStart / 3600 + hoursWork ,
minutesWork ,
secondsWork
) ,
2022-11-02 13:22:18 +00:00
manual : true ,
direction : 'out' ,
isSendMail : true
} , myOptions ) ;
} else {
const weekDay = day . dated . getDay ( ) ;
2023-06-02 10:22:27 +00:00
const journeys = await models . BusinessSchedule . find ( {
2022-11-02 13:22:18 +00:00
where : {
2023-06-02 10:22:27 +00:00
businessFk : day . businessFk ,
weekday : weekDay
2022-10-31 06:34:34 +00:00
}
2022-11-02 13:22:18 +00:00
} , myOptions ) ;
let timeTableDecimalInSeconds = 0 ;
for ( let journey of journeys ) {
2023-01-16 14:18:24 +00:00
const start = Date . vnNew ( ) ;
2023-06-02 10:22:27 +00:00
const [ startHours , startMinutes , startSeconds ] = getTime ( journey . started ) ;
2022-11-03 14:00:55 +00:00
start . setHours ( startHours , startMinutes , startSeconds , 0 ) ;
2022-11-02 13:22:18 +00:00
2023-01-16 14:18:24 +00:00
const end = Date . vnNew ( ) ;
2023-06-02 10:22:27 +00:00
const [ endHours , endMinutes , endSeconds ] = getTime ( journey . ended ) ;
2022-11-03 14:00:55 +00:00
end . setHours ( endHours , endMinutes , endSeconds , 0 ) ;
2022-11-02 13:22:18 +00:00
const result = ( end - start ) / 1000 ;
timeTableDecimalInSeconds += result ;
2022-10-31 06:34:34 +00:00
}
2022-11-02 13:22:18 +00:00
for ( let journey of journeys ) {
const timeTableDecimal = timeTableDecimalInSeconds / 3600 ;
if ( day . timeWorkDecimal == timeTableDecimal ) {
2022-10-31 12:00:32 +00:00
const timed = new Date ( day . dated ) ;
2023-06-02 10:22:27 +00:00
const [ startHours , startMinutes , startSeconds ] = getTime ( journey . started ) ;
2022-10-31 06:34:34 +00:00
await models . WorkerTimeControl . create ( {
userFk : day . workerFk ,
2022-11-02 13:22:18 +00:00
timed : timed . setHours ( startHours , startMinutes , startSeconds ) ,
2022-10-31 06:34:34 +00:00
manual : true ,
isSendMail : true
} , myOptions ) ;
2023-06-02 10:22:27 +00:00
const [ endHours , endMinutes , endSeconds ] = getTime ( journey . ended ) ;
2022-10-31 06:34:34 +00:00
await models . WorkerTimeControl . create ( {
userFk : day . workerFk ,
2022-11-02 13:22:18 +00:00
timed : timed . setHours ( endHours , endMinutes , endSeconds ) ,
2022-10-31 06:34:34 +00:00
manual : true ,
isSendMail : true
} , myOptions ) ;
2022-11-02 13:22:18 +00:00
} else {
const minStart = journeys . reduce ( function ( prev , curr ) {
return curr . start < prev . start ? curr : prev ;
} ) ;
if ( journey == minStart ) {
const timed = new Date ( day . dated ) ;
2023-06-02 10:22:27 +00:00
const [ startHours , startMinutes , startSeconds ] = getTime ( journey . started ) ;
2022-11-02 13:22:18 +00:00
await models . WorkerTimeControl . create ( {
userFk : day . workerFk ,
timed : timed . setHours ( startHours , startMinutes , startSeconds ) ,
manual : true ,
isSendMail : true
} , myOptions ) ;
const [ hoursWork , minutesWork , secondsWork ] = getTime ( day . timeWorkSexagesimal ) ;
await models . WorkerTimeControl . create ( {
userFk : day . workerFk ,
timed : timed . setHours (
startHours + hoursWork ,
startMinutes + minutesWork ,
startSeconds + secondsWork
) ,
manual : true ,
isSendMail : true
} , myOptions ) ;
}
}
2022-11-07 11:21:14 +00:00
if ( day . timeWorkDecimal >= workerTimeControlConfig . timeToBreakTime / 3600 ) {
2022-11-02 13:22:18 +00:00
const minStart = journeys . reduce ( function ( prev , curr ) {
return curr . start < prev . start ? curr : prev ;
} ) ;
if ( journey == minStart ) {
const timed = new Date ( day . dated ) ;
2023-06-02 10:22:27 +00:00
const [ startHours , startMinutes , startSeconds ] = getTime ( journey . started ) ;
2022-11-02 13:22:18 +00:00
await models . WorkerTimeControl . create ( {
userFk : day . workerFk ,
timed : timed . setHours ( startHours + 1 , startMinutes , startSeconds ) ,
manual : true ,
isSendMail : true
} , myOptions ) ;
await models . WorkerTimeControl . create ( {
userFk : day . workerFk ,
timed : timed . setHours ( startHours + 1 , startMinutes + 20 , startSeconds ) ,
manual : true ,
isSendMail : true
} , myOptions ) ;
}
2022-10-31 06:34:34 +00:00
}
}
2022-11-02 13:22:18 +00:00
const timed = new Date ( day . dated ) ;
const firstWorkerTimeControl = await models . WorkerTimeControl . findOne ( {
where : {
userFk : day . workerFk ,
timed : { between : [ timed . setHours ( 0 , 0 , 0 , 0 ) , timed . setHours ( 23 , 59 , 59 , 999 ) ] }
} ,
order : 'timed ASC'
} , myOptions ) ;
if ( firstWorkerTimeControl )
2023-01-18 12:05:02 +00:00
await firstWorkerTimeControl . updateAttribute ( 'direction' , 'in' , myOptions ) ;
2022-11-02 13:22:18 +00:00
const lastWorkerTimeControl = await models . WorkerTimeControl . findOne ( {
where : {
userFk : day . workerFk ,
timed : { between : [ timed . setHours ( 0 , 0 , 0 , 0 ) , timed . setHours ( 23 , 59 , 59 , 999 ) ] }
} ,
order : 'timed DESC'
} , myOptions ) ;
if ( lastWorkerTimeControl )
2023-01-18 12:05:02 +00:00
await lastWorkerTimeControl . updateAttribute ( 'direction' , 'out' , myOptions ) ;
2022-10-31 06:34:34 +00:00
}
2022-11-02 13:22:18 +00:00
}
2022-10-31 06:34:34 +00:00
2022-11-02 13:22:18 +00:00
const lastDay = days [ index ] [ days [ index ] . length - 1 ] ;
if ( day . workerFk != previousWorkerFk || day == lastDay ) {
2023-04-05 13:14:42 +00:00
const query = ` INSERT IGNORE INTO workerTimeControlMail (workerFk, year, week)
VALUES ( ? , ? , ? ) ; ` ;
await Self . rawSql ( query , [ previousWorkerFk , args . year , args . week ] ) ;
2022-10-31 06:34:34 +00:00
2023-04-03 19:29:02 +00:00
ctx . args = {
recipient : previousReceiver ,
year : args . year ,
week : args . week ,
workerId : previousWorkerFk ,
state : 'SENDED'
} ;
await models . WorkerTimeControl . weeklyHourRecordEmail ( ctx , myOptions ) ;
2022-10-31 06:34:34 +00:00
2022-11-02 13:22:18 +00:00
previousWorkerFk = day . workerFk ;
previousReceiver = day . receiver ;
2022-10-31 06:34:34 +00:00
}
2022-11-04 12:41:38 +00:00
2023-01-19 07:54:26 +00:00
if ( tx ) {
await tx . commit ( ) ;
delete myOptions . transaction ;
}
2023-01-18 13:23:05 +00:00
} catch ( e ) {
if ( tx ) await tx . rollback ( ) ;
throw e ;
}
2022-10-31 06:34:34 +00:00
}
2023-01-18 13:23:05 +00:00
return true ;
2022-10-31 06:34:34 +00:00
} ;
2022-11-02 13:22:18 +00:00
function getStartDateOfWeekNumber ( week , year ) {
const simple = new Date ( year , 0 , 1 + ( week - 1 ) * 7 ) ;
const dow = simple . getDay ( ) ;
const weekStart = simple ;
if ( dow <= 4 )
weekStart . setDate ( simple . getDate ( ) - simple . getDay ( ) + 1 ) ;
else
weekStart . setDate ( simple . getDate ( ) + 8 - simple . getDay ( ) ) ;
return weekStart ;
}
function getTime ( timeString ) {
const [ hours , minutes , seconds ] = timeString . split ( ':' ) ;
return [ parseInt ( hours ) , parseInt ( minutes ) , parseInt ( seconds ) ] ;
}
2022-10-31 06:34:34 +00:00
} ;