// @ts-check
/**
* @import {ExpressRequestAuthorized, ExpressResponse} from '../../types.js'
*/
import {query, transaction, UUID2hex, HEX2uuid} from '@commtool/sql-query'
import { parseTimestampToSeconds } from '../../utils/parseTimestamp.js'
import { queueAdd } from '../../tree/treeQueue/treeQueue.js'
import { isObjectAdmin, isObjectVisible } from '../../utils/authChecks.js'
import { errorLoggerUpdate } from '../../utils/requestLogger.js'
import { Templates } from '../../utils/compileTemplates.js'
import { renderObject } from '../../utils/renderTemplates.js'
import { getUID, isValidUID } from '../../utils/UUIDs.js'
import { addUpdateList } from '../../server.ws.js'
import { jobQualified } from './utilities.js'
import { publishEvent } from '../../utils/events.js'
import { publishGroupEvent } from '../person/personHelpers.js'
/**
* Inserts or updates a job in the system.
*
* This function handles the creation of a job for a member in a specific group with a specified function.
* It performs several authorization checks and validations before proceeding with the insertion.
*
* @async
* @function insertOrUpdateJob
* @param {Object} req - The HTTP request object
* @param {Object} req.query - Query parameters
* @param {number} [req.query.timestamp] - Optional timestamp for the job
* @param {Object} req.params - URL parameters
* @param {string} req.params.group - UUID of the group
* @param {string} req.params.member - UUID of the member
* @param {string} req.params.function - UUID of the function
* @param {Object} req.body - Request body
* @param {string} req.body.UID - UUID of the job to be created
* @param {Object} req.session - Session information
* @param {string} req.session.user - Current user's UUID
* @param {string} req.session.root - Root UUID
* @param {Object} res - The HTTP response object
*
* @returns {Promise<void>} - Sends a JSON response with success status and result or error message
*
* @throws {Error} - Logs errors through errorLoggerUpdate
*/
export const insertJob= async (req,res)=>
{
try {
const timestamp = parseTimestampToSeconds(req.query.timestamp ? String(req.query.timestamp) : undefined);
if(!await isObjectAdmin(req,req.params.group))
{
res.status(300).json({success:false,message: 'user not authorized for this group'})
return
}
if(!await isObjectVisible(req,req.params.member))
{
res.status(300).json({success:false,message: 'user not authorized for this person'})
return
}
const groupUID=UUID2hex(req.params.group)
const memberUID=UUID2hex(req.params.member)
const functionUID=UUID2hex(req.params.function)
const jobUID=await getUID(req)
// avoid duplications
const exists=await query(`SELECT ObjectBase.UID FROM
ObjectBase INNER JOIN Links AS GLink ON (GLink.UID=ObjectBase.UID AND GLink.Type='memberA' )
INNER JOIN Links AS FLink ON (FLink.UIDTarget=ObjectBase.UID AND FLink.Type='function')
WHERE GLink.UIDTarget=? AND FLink.UID=? AND ObjectBase.UIDBelongsTo=? AND ObjectBase.Type='job'
`,[groupUID,functionUID,memberUID])
if(exists.length)
{
res.json({success:false,message:'this job exists already for this person in this group'})
return
}
const jobs = await query(`SELECT Data FROM ObjectBase WHERE UID=? AND Type='job'`,[jobUID],{cast:['json']})
if(jobs.length)
{
res.json({success:false,message:'a job with this UID already exists'})
return
}
const functionTemplates=await query(`SELECT Data FROM ObjectBase WHERE UID=?`,[functionUID],{cast:['json']})
if(!functionTemplates.length)
{
res.status(300).json({success:false,message:'missing or unkown UIDfunction'})
}
else
{
const functionTemplate=functionTemplates[0]
const functionData=functionTemplate.Data
const members=await query(`SELECT Data FROM Member WHERE UID=? `,[memberUID],{cast:['json']})
if(!members.length)
{
res.status(300).json({success:false,message:'invalid member UID'})
}
else
{
const member=members[0]
const [group]=await query(`SELECT Member.Data
FROM ObjectBase
INNER JOIN Member ON (Member.UID=ObjectBase.UID)
WHERE ObjectBase.UID=? AND ObjectBase.Type='group'`,[groupUID],{cast:['json']})
if(!group)
{
res.status(300).json({success:false,message:'invalid group UID'})
}
else
{
const qualified=await jobQualified(memberUID,functionData.qualification,timestamp)
const template= Templates[req.session.root].job
const objectData= {
group:{...group.Data,UID:req.params.group},
function:{...functionData,functionUID:req.params.function},
member:member.Data,
UID:req.body.UID,
qualified:qualified
}
const object=await renderObject(template,objectData,req)
// delete memberData
objectData.member=undefined
if(!isValidUID(req.body.UID))
{
res.res.status(300).json({success:false,message:'invalid UID format in body.UID'})
}
await transaction(async (connection)=>
{
await query(`
INSERT INTO ObjectBase (UID,UIDuser,Type,UIDBelongsTo,Title,SortName,dindex,hierarchie,stage,gender,Data)
VALUES (?,?,'job',?,?,?,?,?,?,?,?)
`,
[object.UID,UUID2hex(req.session.user),memberUID,object.Title,object.SortBase,qualified,object.hierarchie,object.stage,object.gender,JSON.stringify(objectData)
])
// Link the job as memberA to the group
await connection.query(
`INSERT IGNORE INTO Links(UID, Type, UIDTarget, UIDuser) VALUES (?,'memberA',?,?)`,
[object.UID,groupUID, UUID2hex(req.session.user)])
// Link the job to his function template
await connection.query(`
INSERT IGNORE INTO Links(UID, Type, UIDTarget,UIDuser) VALUES (?,'function',?,?)`,
[functionUID,object.UID,UUID2hex(req.session.user)]
)
// make sure the job is vsible to the curent user
await connection.query(`INSERT INTO Visible (UID,Type,UIDUser) VALUES(?,'changeable',?)`,
[object.UID,UUID2hex(req.session.user)]
)
},{backDate:timestamp})
// now get the other stuff performed inside the update loop
queueAdd(UUID2hex(req.session.root),UUID2hex(req.session.user),'job',object.UID,jobUID,null,groupUID,timestamp)
addUpdateList(memberUID)
res.json({success:true,result:{...object,UID: HEX2uuid(object.UID)}})
}
}
}
}
catch(e)
{
errorLoggerUpdate(e)
}
}