]> PHS Git Server - phs-api.git/commitdiff
Cleaning up the user model file.
authorcharleswrayjr <charleswrayjr@gmail.com>
Fri, 12 Sep 2025 01:24:57 +0000 (20:24 -0500)
committercharleswrayjr <charleswrayjr@gmail.com>
Fri, 12 Sep 2025 01:24:57 +0000 (20:24 -0500)
src/models/user.model.js

index e7c560eb97f747d4a2b587145b536c51eefe281a..5e3af78f6fa564b5bb65f1f5e1c0758e71398007 100644 (file)
@@ -1,8 +1,8 @@
 /**
- * @file User model for the users table
+ * @file User model for phase.users table
  */
 
-const { Model, ValidationError } = require('./model');
+const { Model, ValidationError } = require( './model' );
 
 /**
  * @typedef {Object} User
@@ -12,6 +12,7 @@ const { Model, ValidationError } = require('./model');
  * @property {string} middle_name - User's middle name
  * @property {string} last_name - User's last name
  * @property {string|null} initials - User's initials
+ * @property {string|null} nickname - User's nickname (unique)
  * @property {number|null} created_by_id - ID of user who created this user
  * @property {Date} created_at - Creation timestamp
  * @property {boolean} is_deleted - Soft delete flag
@@ -31,31 +32,53 @@ class User extends Model {
    * Create a User instance
    * @param {Partial<User>} [props] - User properties
    */
-  constructor(props) {
-    super(props);
+  constructor( props ) {
+    super( props );
     this.table = 'phase.users';
     this.prepend = 'u';
     this.default_columns = [
-      'id', 'email', 'first_name', 'middle_name', 'last_name', 'initials',
+      'id', 'email', 'first_name', 'middle_name', 'last_name', 'initials', 'nickname',
       'created_by_id', 'created_at', 'is_deleted', 'deleted_by_id', 'deleted_at',
       'is_active', 'deactivated_by_id', 'deactivated_at'
     ];
     this.update_exclude_columns = ['id', 'created_at', 'is_deleted', 'deleted_at', 'deleted_by_id'];
     this.base_query = `
-        SELECT u.id, u.email, u.first_name, u.middle_name, u.last_name, u.initials,
-               u.created_by_id, u.created_at, u.is_deleted, u.deleted_by_id, u.deleted_at,
-               u.is_active, u.deactivated_by_id, u.deactivated_at
+        SELECT u.id,
+               u.email,
+               u.first_name,
+               u.middle_name,
+               u.last_name,
+               u.initials,
+               u.nickname,
+               u.created_by_id,
+               u.created_at,
+               u.is_deleted,
+               u.deleted_by_id,
+               u.deleted_at,
+               u.is_active,
+               u.deactivated_by_id,
+               u.deactivated_at
         FROM phase.users u
         WHERE u.is_deleted = false
     `;
     this.base_list_query = `
-        SELECT u.id, u.email, u.first_name, u.middle_name, u.last_name, u.initials,
-               u.created_by_id, u.created_at, u.is_active, u.deactivated_by_id, u.deactivated_at
+        SELECT u.id,
+               u.email,
+               u.first_name,
+               u.middle_name,
+               u.last_name,
+               u.initials,
+               u.nickname,
+               u.created_by_id,
+               u.created_at,
+               u.is_active,
+               u.deactivated_by_id,
+               u.deactivated_at
         FROM phase.users u
         WHERE u.is_deleted = false
     `;
     this.default_order_by = 'ORDER BY u.email ASC';
-    this.instance = _props => new User(_props);
+    this.instance = _props => new User( _props );
   }
 
   /**
@@ -64,69 +87,27 @@ class User extends Model {
    * @returns {Promise<User>} Created user instance
    * @throws {ValidationError} If required fields are missing
    */
-  static async create(user_data) {
+  static async create( user_data ) {
     const {
-      email, first_name, middle_name = '', last_name, initials = null,
+      email, first_name, middle_name = '', last_name, initials = null, nickname = null,
       created_by_id = null, is_active = true, deactivated_by_id = null, deactivated_at = null
     } = user_data;
     if (!email || !first_name || !last_name) {
-      throw new ValidationError('Missing required fields: email, first_name, last_name');
+      throw new ValidationError( 'Missing required fields: email, first_name, last_name' );
     }
     const query_str = `
-        INSERT INTO phase.users (
-            email, first_name, middle_name, last_name, initials, created_by_id,
-            is_active, deactivated_by_id, deactivated_at
-        ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING *;
+        INSERT INTO phase.users (email, first_name, middle_name, last_name, initials, nickname, created_by_id,
+                                 is_active, deactivated_by_id, deactivated_at)
+        VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
+        RETURNING *;
     `;
     const values = [
-      email, first_name, middle_name, last_name, initials, created_by_id,
-      is_active, deactivated_by_id, deactivated_at
+      email, first_name, middle_name, last_name, initials, nickname,
+      created_by_id, is_active, deactivated_by_id, deactivated_at
     ];
-    const result = await phsdb.query(query_str, values, { plain: true });
-    if (!result) throw new ValidationError('Failed to create user');
-    await this.createPhoneNumbers();
-    await this.createAddresses();
-    await this.createNickNames();
-    return new User(result);
-  };
-
-  static async createPhoneNumbers( phone_numbers) {
-    if (phone_numbers?.length > 0) {
-      const pn = Array.from( new Set( phone_numbers ) );
-      const phoneArray = [];
-      for (let phone_number of pn) {
-        const phone = await require('./phone_number.model').create(phone_number);
-        await phone.add_user(this.id)
-          .then( result => phoneArray.push(result) )
-          .catch( err => throw new ValidationError( err.message ) );
-      }
-    } else return true;
-  };
-
-  static async createAddresses( addresses) {
-    if (addresses?.length > 0) {
-      const addr = Array.from( new Set( addresses ) );
-      const addrArray = [];
-      for (let address of addr) {
-        const _address = await require('./address.model').create(address);
-        await _address.add_user(this.id)
-          .then( result => addrArray.push(result) )
-          .catch( err => throw new ValidationError( err.message ) );
-      }
-    } else return true;
-  };
-
-  static async createNickNames( nicknames) {
-    if (nicknames?.length > 0) {
-      const names = Array.from( new Set( nicknames ) );
-      const nameArray = [];
-      for (let name of names) {
-        const nickname = await require('./nickname.model').create(name);
-        await nickname.add_relation(this.id)
-          .then( result => nameArray.push(result) )
-          .catch( err => throw new ValidationError( err.message ) );
-      }
-    } else return true;
+    const result = await phsdb.query( query_str, values, { plain:true } );
+    if (!result) throw new ValidationError( 'Failed to create user' );
+    return new User( result );
   };
 
   /**
@@ -135,8 +116,19 @@ class User extends Model {
    * @param {string[]} [excludes] - Fields to exclude from result
    * @returns {Promise<User|null>} User instance or null
    */
-  static async find_by_email(email, excludes = []) {
-    return await new User().find_one({ email }, excludes);
+  static async find_by_email( email, excludes = [] ) {
+    return await new User().find_one( { email }, excludes );
+  }
+
+  // noinspection JSUnusedGlobalSymbols
+  /**
+   * Find user by nickname
+   * @param {string} nickname - Nickname to search for
+   * @param {string[]} [excludes] - Fields to exclude from result
+   * @returns {Promise<User|null>} User instance or null
+   */
+  static async find_by_nickname( nickname, excludes = [] ) {
+    return await new User().find_one( { nickname }, excludes );
   }
 
   /**
@@ -147,9 +139,9 @@ class User extends Model {
    * @param {number} [offset=0] - Number of records to skip
    * @returns {Promise<User[]>} Array of active users
    */
-  static async find_active(excludes = [], order_by = null, limit = 100, offset = 0) {
-    return await new User().find_many({ is_active: true }, excludes, order_by, limit, offset);
-  }
+  static async find_active( excludes = [], order_by = null, limit = 100, offset = 0 ) {
+    return await new User().find_many( { is_active:true }, excludes, order_by, limit, offset );
+  };
 
   // noinspection JSUnusedGlobalSymbols
   /**
@@ -160,25 +152,25 @@ class User extends Model {
    * @param {number} [offset=0] - Number of records to skip
    * @returns {Promise<User[]>} Array of deleted users
    */
-  static async find_deleted(excludes = [], order_by = null, limit = 100, offset = 0) {
-    const query_str = this.prototype.base_list_query.replace('WHERE u.is_deleted = false', 'WHERE u.is_deleted = true');
+  static async find_deleted( excludes = [], order_by = null, limit = 100, offset = 0 ) {
+    const query_str = this.prototype.base_list_query.replace( 'WHERE u.is_deleted = false', 'WHERE u.is_deleted = true' );
     const instance = this.prototype.instance;
-    const { keys, values } = this.prototype.build_where({}, this.prototype.default_columns);
-    values.push(limit, offset);
+    const { keys, values } = this.prototype.build_where( {}, this.prototype.default_columns );
+    values.push( limit, offset );
     const results = await phsdb.query(
       `
-        ${query_str}
-        ${this.prototype.where_clause(keys, this.prototype.prepend)}
-        ${order_by ? `ORDER BY ${order_by.name} ${order_by.direction ?? 'asc'}` : this.prototype.default_order_by ?? ''}
-        LIMIT $${values.length - 1} OFFSET $${values.length}
+        ${ query_str }
+        ${ this.prototype.where_clause( keys, this.prototype.prepend ) }
+        ${ order_by ? `ORDER BY ${ order_by.name } ${ order_by.direction ?? 'asc' }` : this.prototype.default_order_by ?? '' }
+        LIMIT $${ values.length - 1 } OFFSET $${ values.length }
       `,
       values
     );
-    return results.map(result => {
-      const found = instance(result);
-      excludes?.forEach(e => delete found[e]);
+    return results.map( result => {
+      const found = instance( result );
+      excludes?.forEach( e => delete found[e] );
       return found;
-    });
+    } );
   }
 
   /**
@@ -187,16 +179,16 @@ class User extends Model {
    * @returns {Promise<User>} Updated user instance
    * @throws {ValidationError} If deactivated_by_id is invalid
    */
-  async deactivate(deactivated_by_id) {
-    const deactivated_by_id_int = parseInt(deactivated_by_id, 10);
-    if (isNaN(deactivated_by_id_int)) {
-      throw new ValidationError('deactivated_by_id must be a valid integer');
+  async deactivate( deactivated_by_id ) {
+    const deactivated_by_id_int = parseInt( deactivated_by_id, 10 );
+    if (isNaN( deactivated_by_id_int )) {
+      throw new ValidationError( 'deactivated_by_id must be a valid integer' );
     }
-    return await this.update({
-      is_active: false,
-      deactivated_at: new Date().toISOString(),
-      deactivated_by_id: deactivated_by_id_int
-    });
+    return await this.update( {
+      is_active:false,
+      deactivated_at:new Date().toISOString(),
+      deactivated_by_id:deactivated_by_id_int
+    } );
   }
 
   /**
@@ -204,11 +196,11 @@ class User extends Model {
    * @returns {Promise<User>} Updated user instance
    */
   async reactivate() {
-    return await this.update({
-      is_active: true,
-      deactivated_at: null,
-      deactivated_by_id: null
-    });
+    return await this.update( {
+      is_active:true,
+      deactivated_at:null,
+      deactivated_by_id:null
+    } );
   }
 
   /**
@@ -217,16 +209,16 @@ class User extends Model {
    * @returns {Promise<User>} Updated user 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');
+  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' );
     }
-    return await this.update({
-      is_deleted: true,
-      deleted_at: new Date().toISOString(),
-      deleted_by_id: deleted_by_id_int
-    });
+    return await this.update( {
+      is_deleted:true,
+      deleted_at:new Date().toISOString(),
+      deleted_by_id:deleted_by_id_int
+    } );
   }
 
   /**
@@ -237,16 +229,6 @@ class User extends Model {
     return this.is_active === true;
   }
 
-  // noinspection JSUnusedGlobalSymbols
-  /**
-   * Get the user who created this user
-   * @returns {Promise<User|null>} Creator user instance or null
-   */
-  async get_created_by() {
-    if (!this.created_by_id) return null;
-    return await new User().find_one({ id: this.created_by_id }, []);
-  }
-
   // noinspection JSUnusedGlobalSymbols
   /**
    * Get user data without sensitive information