Source: Router/achievementTemplate/controller.js

/**
 * Achievement Template Controller
 * 
 * Contains all the business logic for achievement template operations:
 * - Creating and updating achievement templates
 * - Deleting achievement templates
 * - Retrieving achievement templates (with and without data)
 * 
 * All functions handle proper authorization checks and template updates.
 */

import { query, transaction, UUID2hex, HEX2uuid } from '@commtool/sql-query';
import { renderObject } from '../../utils/renderTemplates.js';
import { Templates } from '../../utils/compileTemplates.js';
import { getUID } from '../../utils/UUIDs.js';
import { updateTemplate } from '../../server.ws.js';
import { errorLoggerUpdate, errorLoggerRead } from '../../utils/requestLogger.js';

/**
 * Creates or updates an achievement template
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
export const createOrUpdateAchievementTemplate = async (req, res) => {
    try {
        const template = Templates[req.session.root].achievementTemplate;
        const UIDachievement = await getUID(req);
        const object = await renderObject(template, req.body, req);
        
        object.Data = { ...req.body, UID: undefined };
        
        await query(`
            INSERT INTO ObjectBase(UID,Type,UIDBelongsTo,Title,Display,SortName, FullTextIndex, Data)
            VALUES (?,'achievementT',?,?,?,?,?,?)
            ON DUPLICATE KEY UPDATE Title=VALUE(Title),Display=VALUE(Display),SortName=VALUE(SortName),FullTextIndex=VALUE(FullTextIndex),Data=VALUE(Data)`,
            [object.UID, UUID2hex(req.session.root), object.Title, object.Display, object.SortIndex, object.FullTextIndex, JSON.stringify(object.Data)]);

        updateTemplate(req.session.root);
        res.json({ success: true, result: { ...object, UID: HEX2uuid(object.UID) } });
    } catch (e) {
        errorLoggerUpdate(e);
        res.status(500).json({ success: false, message: 'Internal server error' });
    }
};

/**
 * Deletes an achievement template
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
export const deleteAchievementTemplate = async (req, res) => {
    try {
        const UID = UUID2hex(req.params.UID);
        
        await query(`DELETE FROM ObjectBase WHERE UID=? AND Type='achievementT'
                    AND UIDBelongsTo=?`, [UID, UUID2hex(req.session.root)]);
        
        await transaction(async (connection) => {
            await connection.query(`DELETE ObjectBase,Links FROM ObjectBase 
            INNER JOIN Links ON (Links.UID=ObjectBase.UID AND Links.Type='achievement')
            WHERE Links.UIDTarget=?`, [UID]);
        }, {
            beforeTransaction: async (connection) => await connection.query(`SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;`)
        });
        
        updateTemplate(req.session.root);
        res.json({ success: true });
    } catch (e) {
        errorLoggerUpdate(e);
        res.status(500).json({ success: false, message: 'Internal server error' });
    }
};

/**
 * Gets all achievement templates for the organization
 * @param {Object} req - Express request object
 * @param {Object} res - Express response object
 */
export const getAchievementTemplates = async (req, res) => {
    try {
        // Conditionally include template data - can be large
        let mainData = '';
        if (req.query.includeData === 'true') {
            mainData = ', Main.Data';
        }
        
        const result = await query(`

            SELECT
                Main.UID, Main.Display, Main.SortName ${mainData}
            FROM
                ObjectBase AS Main
            WHERE
            Main.UIDBelongsTo=? AND Main.Type='achievementT'
            GROUP BY
            Main.UID
            ORDER BY
                Main.dindex      
            `, [UUID2hex(req.session.root)], { cast: ['UUID', 'json'] });
        
        res.json({ success: true, result: result });
    } catch (e) {
        errorLoggerRead(e);
        res.status(500).json({ success: false, message: 'Internal server error' });
    }
};