+++ /dev/null
-/**
- * @file Nickname model for phase.nicknames table
- */
-
-const { Model, ValidationError } = require('./model');
-const User = require( './user.model' );
-
-/**
- * @typedef {Object} Nickname
- * @property {number} id - Nickname ID (primary key)
- * @property {string} nickname - Nickname value
- * @property {number|null} created_by_id - ID of user who created this nickname
- * @property {Date} created_at - Creation timestamp
- * @property {boolean} is_deleted - Soft delete flag
- * @property {number|null} deleted_by_id - ID of user who deleted this nickname
- * @property {Date|null} deleted_at - Deletion timestamp
- */
-
-/**
- * Nickname model class
- * @extends Model
- */
-class Nickname extends Model {
- /**
- * Create a Nickname instance
- * @param {Partial<Nickname>} [props] - Nickname properties
- */
- constructor(props) {
- super(props);
- this.table = 'phase.nicknames';
- this.prepend = 'n';
- this.default_columns = [
- 'id', 'nickname', 'created_by_id', 'created_at',
- 'is_deleted', 'deleted_by_id', 'deleted_at'
- ];
- this.update_exclude_columns = ['id', 'created_at', 'is_deleted', 'deleted_at', 'deleted_by_id'];
- this.base_query = `
- SELECT n.id, n.nickname, n.created_by_id, n.created_at,
- n.is_deleted, n.deleted_by_id, n.deleted_at
- FROM phase.nicknames n
- WHERE n.is_deleted = false
- `;
- this.base_list_query = `
- SELECT n.id, n.nickname, n.created_by_id, n.created_at
- FROM phase.nicknames n
- WHERE n.is_deleted = false
- `;
- this.default_order_by = 'ORDER BY n.nickname ASC';
- this.instance = _props => new Nickname(_props);
- }
-
- /**
- * Create a new nickname
- * @param {Omit<Nickname, 'id'|'created_at'|'is_deleted'|'deleted_by_id'|'deleted_at'>} nickname_data - Nickname data
- * @returns {Promise<Nickname>} Created nickname instance
- * @throws {ValidationError} If required fields are missing
- */
- static async create(nickname_data) {
- const { nickname, created_by_id = null } = nickname_data;
- if (!nickname) throw new ValidationError('Missing required field: nickname');
- const query_str = `
- INSERT INTO phase.nicknames (nickname, created_by_id)
- VALUES ($1, $2) RETURNING *;
- `;
- const values = [nickname, created_by_id];
- const result = await phsdb.query(query_str, values, { plain: true });
- if (!result) throw new ValidationError('Failed to create nickname');
- return new Nickname(result);
- };
-
- /**
- * Create the relation between a user and a nickname
- * @param user_id
- * @returns {Promise<{user_id: number, nickname_id: number}>}
- */
- static async add_user(user_id) {
- const done = await require( 'user_nickname.model' ).add_relation( user_id, this.id );
- if (!done) throw new ValidationError('Failed to add nickname');
- return done;
- };
-
- async get_with_associated_users( id = null, excludes = [] ) {
- const id_int = parseInt( id, 10 );
- let query_str = `
- SELECT n.id, n.nickname, n.created_by_id, n.created_at, concat(db.first_name, ' ', db.last_name) as deleted_by,
- n.is_deleted, n.deleted_by_id, n.deleted_at, concat(cr.first_name, ' ', cr.last_name) as created_by
- FROM phase.nicknames n
- LEFT JOIN phase.users cr ON n.created_by_id = cr.id
- LEFT JOIN phase.users db ON n.deleted_by_id = db.id
- WHERE n.is_deleted = false
- `;
- const values = [];
- if (id_int) {
- query_str += ` AND n.id = $1;`;
- values.push( id_int );
- }
- const result = await phsdb.query(query_str, values, { plain: !isNaN(id_int) } );
- if (!result) throw new ValidationError('Failed to get nickname');
- else return result;
- };
-
- /**
- * Find nickname by value
- * @param {string} nickname - Nickname to search for
- * @param {string[]} [excludes] - Fields to exclude from result
- * @returns {Promise<Nickname|null>} Nickname instance or null
- */
- static async find_by_nickname(nickname, excludes = []) {
- return await new Nickname().find_one({ nickname }, excludes);
- }
-
- /**
- * Soft delete a nickname and remove the relation between the nickname and any users that it is associated with.
- * @param {number|string} deleted_by_id - ID of user performing deletion
- * @returns {Promise<Nickname>} Updated nickname instance
- * @throws {ValidationError} If deleted_by_id is invalid
- */
- async soft_delete(deleted_by_id) {
- const deleted_by_id_int = parseInt(deleted_by_id, 10);
- if (isNaN(deleted_by_id_int)) {
- throw new ValidationError('deleted_by_id must be a valid integer');
- }
- await require( 'user_nickname.model' ).remove_relation( this.id );
- return await this.update({
- is_deleted: true,
- deleted_at: new Date().toISOString(),
- deleted_by_id: deleted_by_id_int
- });
- }
-
- /**
- * Get the user who created this nickname
- * @returns {Promise<User|null>} Creator user instance or null
- */
- async get_created_by() {
- if (!this.created_by_id) return null;
- const User = require('./user.model');
- return await new User().find_one({ id: this.created_by_id }, []);
- }
-
- /**
- * Get the user who deleted this nickname
- * @returns {Promise<User|null>} Deleter user instance or null
- */
- async get_deleted_by() {
- if (!this.deleted_by_id) return null;
- const User = require('./user.model');
- return await new User().find_one({ id: this.deleted_by_id }, []);
- }
-}
-
-module.exports = Nickname;
\ No newline at end of file
+++ /dev/null
-/**
- * @file User nicknames model for phase.user_nicknames table
- */
-
-const { Model, ValidationError } = require( './model' );
-
-/**
- * @typedef {Object} UserNickname
- * @property {number} user_id - User ID (foreign key)
- * @property {number} nickname_id - Nickname ID (foreign key)
- */
-
-/**
- * User nickname model class
- * @extends Model
- */
-class UserNickname extends Model {
- /**
- * Create a UserNickname instance
- * @param {Partial<UserNickname>} [props] - User nickname properties
- */
- constructor( props ) {
- super( props );
- this.table = 'phase.user_nicknames';
- this.prepend = 'un';
- this.default_columns = ['user_id', 'nickname_id'];
- this.update_exclude_columns = ['user_id', 'nickname_id'];
- this.base_query = `
- SELECT un.user_id, un.nickname_id
- FROM phase.user_nicknames un
- `;
- this.base_list_query = this.base_query;
- this.default_order_by = 'ORDER BY un.user_id ASC';
- this.instance = _props => new UserNickname( _props );
- };
-
- /**
- * Add a user-nickname relation
- * @param {number|string} user_id - User ID
- * @param {number|string} nickname_id - Nickname ID
- * @returns {Promise<UserNickname>} Created relation instance
- * @throws {ValidationError} If IDs are invalid
- */
- static async add_relation( user_id, nickname_id ) {
- const user_id_int = parseInt( user_id, 10 );
- const nickname_id_int = parseInt( nickname_id, 10 );
- if (isNaN( user_id_int ) || isNaN( nickname_id_int )) {
- throw new ValidationError( 'user_id and nickname_id must be valid integers' );
- }
- const query_str = `
- INSERT INTO phase.user_nicknames (user_id, nickname_id)
- VALUES ($1, $2)
- RETURNING *;
- `;
- const values = [user_id_int, nickname_id_int];
- const result = await phsdb.query( query_str, values, { plain:true } );
- if (!result) throw new ValidationError( 'Failed to add user-nickname relation' );
- return new UserNickname( result );
- };
-
- /**
- * Remove a user-nickname relation
- * @param {number|string} nickname_id - Nickname ID
- * @param {number|string|undefined} [user_id = undefined] - User ID
- * @returns {Promise<UserNickname|null>} Deleted relation instance or null
- * @throws {ValidationError} If IDs are invalid
- */
- static async remove_relation( nickname_id, user_id = undefined ) {
- const user_id_int = parseInt( user_id, 10 );
- const nickname_id_int = parseInt( nickname_id, 10 );
- if (isNaN( nickname_id_int )) {
- throw new ValidationError( 'nickname_id must be valid integers' );
- }
- const query_str = `
- DELETE
- FROM phase.user_nicknames
- WHERE nickname_id = $1 ${ user_id ? 'AND user_id = $2' : '' }
- RETURNING *;
- `;
- const values = [nickname_id_int];
- if (!isNaN( user_id_int )) values.push( user_id_int );
- const result = await phsdb.query( query_str, values, { plain: !isNaN( user_id_int ) } );
- return result ? new UserNickname( result ) : null;
- };
-}
-
-module.exports = UserNickname;
\ No newline at end of file