Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] Internal system notifications #8758

Open
wants to merge 32 commits into
base: develop
Choose a base branch
from

Conversation

GloireMutaliko21
Copy link
Contributor

@GloireMutaliko21 GloireMutaliko21 commented Jan 26, 2025

PR

Please note: we will close your PR without comment if you do not check the boxes above and provide ALL requested information.


Summary by CodeRabbit

  • New Features

    • Launched enhanced employee notifications with tailored settings for assignments, mentions, comments, and subscriptions.
    • Introduced smooth notification handling during task creation, comment publishing, and mention events.
  • Refactor

    • Streamlined underlying data models and integrations to improve consistency across core features.

Copy link
Contributor

coderabbitai bot commented Jan 26, 2025

Walkthrough

This pull request refactors configuration files and updates multiple data models. It removes tenant/organization inheritance in favor of a simplified base entity, introduces new models, interfaces, migrations, DTOs, commands, and handlers—especially for employee notifications and their settings—and updates various modules such as comments, subscriptions, and tasks. In addition, it adjusts public exports and shared utilities, including renaming a transformer class.

Changes

File(s) Change Summary
nx.json Removed and re-added the full configuration block (formatting/structural change only).
packages/contracts/src/lib/{activity-log, base-entity, comment, favorite, mention, resource-link, subscription, employee-notification*.ts} Removed inheritance from IBasePerTenantAndOrganizationEntityModel in favor of IBasePerEntityType; added new exports and models for employee notifications; introduced new types (e.g., OmitFields<T,K>) and optional entityName property in comment and mention inputs.
packages/core/src/lib/{app/app.module.ts, activity-log/activity-log.entity.ts, comment/comment.entity.ts, core/entities/**, database/migrations/**, favorite/favorite.entity.ts, mention/mention.entity.ts, resource-link/resource-link.entity.ts, subscription/subscription.entity.ts} Updated base class extensions to BasePerEntityType, removed obsolete properties (entity, entityId), and added new abstract classes; new migrations created for user notification and notification setting tables; updated module imports and entity registrations.
packages/core/src/lib/{tasks/**, subscription/**} Enhanced task and subscription flows with updated types (e.g., IEntitySubscription*), added notification publishing via EmployeeNotificationService, and integrated new parameters such as entityName.
packages/core/src/lib/employee-notification/** Introduced a comprehensive employee notification feature including new modules, controllers, services, repositories, DTOs, command handlers, events, and subscribers; added a helper to generate dynamic notification titles and a new transformer for employee notification types.
packages/core/src/lib/shared/pipes/{actor-type-transform.ts, index.ts} Renamed class from ActorTypeTransformerPipe to ActorTypeTransformer and updated corresponding export statements.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Service as Application Service
    participant NotificationSvc as EmployeeNotificationService
    participant Repo as Notification Repository
    participant EventBus

    User->>Service: Create/Update Comment or Task (with entityName)
    Service->>NotificationSvc: publishNotificationEvent(details)
    NotificationSvc->>Repo: Create notification record
    Repo-->>NotificationSvc: Record created
    NotificationSvc->>EventBus: Publish EmployeeCreateNotificationEvent
    EventBus-->>NotificationSvc: Event processed
    NotificationSvc-->>Service: Notification published
Loading

Possibly related PRs

Poem

I’m a little rabbit, hopping in the code,
New paths and models light up my node.
Employee notifications now dance in the air,
Subscriptions and tasks handled with care.
With each change, I nibble and cheer—
CodeRabbit leads, and I’m here to cheer!
🐰💻

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

nx-cloud bot commented Jan 26, 2025

View your CI Pipeline Execution ↗ for commit afa7223.

Command Status Duration Result
nx build ui-core --configuration=development ❌ Failed 1m 23s View ↗
nx build ui-core --configuration=production ❌ Failed 1m 19s View ↗
nx build auth --configuration=development ✅ Succeeded <1s View ↗
nx build plugin ✅ Succeeded <1s View ↗
nx build config ✅ Succeeded <1s View ↗
nx build utils ✅ Succeeded <1s View ↗
nx build common ✅ Succeeded <1s View ↗
nx build contracts ✅ Succeeded <1s View ↗
Additional runs (2) ✅ Succeeded ... View ↗

☁️ Nx Cloud last updated this comment at 2025-02-10 15:10:13 UTC

Copy link

socket-security bot commented Feb 1, 2025

New, updated, and removed dependencies detected. Learn more about Socket for GitHub ↗︎

Package New capabilities Transitives Size Publisher

View full report↗︎

@GloireMutaliko21 GloireMutaliko21 marked this pull request as ready for review February 8, 2025 10:22
Copy link

socket-security bot commented Feb 8, 2025

👍 Dependency issues cleared. Learn more about Socket for GitHub ↗︎

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report↗︎

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🔭 Outside diff range comments (1)
packages/core/src/lib/activity-log/activity-log.entity.ts (1)

69-71: Incorrect decorator for JSON data type.

The data property is decorated with @IsArray() but its type is JsonData which can be either an object or string.

-  @IsArray()
+  @IsOptional()
   @MultiORMColumn({ type: isPostgres() ? 'jsonb' : isMySQL() ? 'json' : 'text', nullable: true })
   data?: JsonData;
🧹 Nitpick comments (26)
packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.entity.ts (1)

1-3: Remove or justify the ESLint disable comment.
If there's no longer a need for "eslint-disable-next-line @typescript-eslint/no-unused-vars" after these changes, consider removing it to maintain a clean codebase.

packages/core/src/lib/mention/mention.entity.ts (1)

12-12: Confirm removal of entity references.
With entityId and entity removed, confirm the rest of the codebase has been updated to avoid referencing these fields (e.g., mentions might need a new strategy for linking to their entities).

packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.subscriber.ts (1)

23-37: Consider using a standardized logger over console.error.
The try/catch block ensures robust error handling, but using a logging service (e.g., NestJS Logger) instead of console.error is often preferred for uniform logging and potential log-level filtering.

packages/core/src/lib/user-notification/user-notification.entity.ts (1)

44-66: Consider synchronizing isRead with readAt.
When isRead is true, readAt could be automatically set (and reset to null if isRead is toggled off), ensuring a consistent data model.

packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.controller.ts (1)

38-83: Optional: Add explicit HttpStatus for POST method.
The POST endpoint returns 201 (created) by default, which is generally correct. However, adding an explicit @httpcode(HttpStatus.CREATED) can improve clarity for anyone reading the code.

packages/core/src/lib/user-notification/user-notification.service.ts (2)

1-28: Use a logging mechanism instead of console.log.
Internally, Nest recommends using a Logger service (e.g., Logger from '@nestjs/common') for better log management and consistency.


81-156: Consider user feedback when ignoring notifications.
In the scenario where notifications are disallowed by user settings, the method silently does nothing. If business requirements require you to track or confirm that a notification was skipped, consider logging this event or returning a status indicating that creation was intentionally bypassed.

packages/core/src/lib/database/migrations/1738217979804-CreateUserNotificationTable.ts (2)

14-14: Consider using a proper logger instead of console.log.
Using a dedicated logging service or methodology (e.g., a NestJS logger) can make logs more configurable, consistent, and maintainable than raw console statements.


213-214: Consider text-type columns for message fields.
For notification messages, 255 characters may be too restrictive if more verbose content is needed. You might consider using TEXT (Postgres) or TEXT-type columns (MySQL) to accommodate longer messages.

- "message" character varying(255), 
+ "message" text,
packages/core/src/lib/user-notification/events/user-notification.event.ts (1)

4-6: Add descriptive comments for the event properties.
Documenting the purpose of the 'input' parameter can improve code readability and help other developers understand the event's payload at a glance.

packages/core/src/lib/user-notification/user-notification-setting/commands/user-notification-setting.create.command.ts (1)

4-8: Consider using a more specific command type string.

The current type string [UserNotificationSetting] Create could potentially conflict with other similar commands. Consider making it more specific to this exact use case.

-	static readonly type = '[UserNotificationSetting] Create';
+	static readonly type = '[User/NotificationSetting] Create Setting';
packages/core/src/lib/user-notification/user-notification-setting/commands/user-notification-setting.update.command.ts (1)

4-8: LGTM! Consider adding JSDoc documentation.

The command implementation follows CQRS pattern correctly with proper immutability. Consider adding JSDoc documentation to describe the command's purpose and parameters.

+/**
+ * Command to update user notification settings
+ * @param id - The ID of the notification setting to update
+ * @param input - The update data for the notification setting
+ */
 export class UserNotificationSettingUpdateCommand implements ICommand {
packages/core/src/lib/user-notification/repository/type-orm-user-notification.repository.ts (1)

7-11: LGTM! Consider adding custom query methods.

The repository implementation follows TypeORM patterns correctly. Consider adding custom query methods for common operations specific to user notifications (e.g., findUnreadNotifications, markAsRead).

@Injectable()
export class TypeOrmUserNotificationRepository extends Repository<UserNotification> {
    // ... existing code ...

    async findUnreadNotifications(userId: string): Promise<UserNotification[]> {
        return this.find({
            where: {
                user: { id: userId },
                isRead: false
            }
        });
    }

    async markAsRead(id: string): Promise<void> {
        await this.update(id, { isRead: true });
    }
}
packages/core/src/lib/user-notification/user-notification-setting/dto/create-user-notification-setting.dto.ts (1)

9-11: Consider adding validation decorators.

While the DTO structure is correct, consider adding class-validator decorators to ensure input validation at the DTO level.

import { IsNotEmpty, IsBoolean, IsOptional } from 'class-validator';

export class CreateUserNotificationSettingDTO
    extends IntersectionType(TenantOrganizationBaseDTO, UserNotificationSetting)
    implements IUserNotificationSettingCreateInput {
    
    @IsNotEmpty()
    @IsBoolean()
    isEnabled: boolean;

    @IsOptional()
    @IsBoolean()
    isArchived?: boolean;
}
packages/contracts/src/lib/user-notification-setting.model.ts (2)

7-13: Consider adding default values and validation for notification flags.

The boolean flags are all optional without default values. Consider:

  1. Setting default values for better predictability
  2. Adding validation constraints
  3. Making some flags required if they are essential

13-13: Consider adding structure to preferences.

The preferences field using JsonData type is very flexible but might benefit from a more structured type definition to ensure type safety and better documentation of expected values.

packages/core/src/lib/user-notification/user-notification-setting/commands/handlers/user-notification-setting.update.handler.ts (1)

17-22: Consider standardizing the return type.

The method returns either IUserNotificationSetting | UpdateResult. This dual return type could make error handling more complex for consumers. Consider standardizing to always return IUserNotificationSetting and handle the update result internally.

-	public async execute(
-		command: UserNotificationSettingUpdateCommand
-	): Promise<IUserNotificationSetting | UpdateResult> {
+	public async execute(
+		command: UserNotificationSettingUpdateCommand
+	): Promise<IUserNotificationSetting> {
 		const { id, input } = command;
-		return this.userNotificationSettingService.update(id, input);
+		const result = await this.userNotificationSettingService.update(id, input);
+		return this.userNotificationSettingService.findOneByIdString(id);
 	}
packages/core/src/lib/user-notification/user-notification.helper.ts (1)

12-36: Consider adding input validation and error handling.

The function should validate inputs and handle missing templates gracefully.

Consider this enhanced implementation:

 export function generateNotificationTitle(
 	action: NotificationActionTypeEnum,
 	entity: BaseEntityEnum,
 	entityName: string,
 	userName: string
 ) {
+	if (!action || !entity || !entityName || !userName) {
+		throw new Error('Missing required parameters for notification title generation');
+	}
+
 	// Get the template corresponding to the action
 	const template = UserNotificationTemplates[action];
+	if (!template) {
+		throw new Error(`No template found for action: ${action}`);
+	}
 
 	// Replace placeholders in the template with actual values
 	return template.replace(/\{(\w+)\}/g, (_, key) => {
 		switch (key) {
 			case 'action':
 				return action;
 			case 'entity':
 				return entity;
 			case 'entityName':
 				return entityName;
 			case 'userName':
 				return userName;
 			default:
-				return '';
+				return `{${key}}`;  // Preserve unrecognized placeholders
 		}
 	});
 }
packages/contracts/src/lib/user-notification.model.ts (1)

20-27: Remove misleading DB storage comments.

The comments about enum values being stored as numbers in DB are implementation-specific and might be misleading.

Apply this diff to remove the comments:

 export enum UserNotificationTypeEnum {
-	PAYMENT = 'Payment', // Will be stored as 0 in DB
-	ASSIGNMENT = 'Assignment', // Will be stored as 1 in DB
-	INVITATION = 'Invitation', // Will be stored as 2 in DB
-	MENTION = 'Mention', // Will be stored as 3 in DB
-	COMMENT = 'Comment', // Will be stored as 4 in DB
-	MESSAGE = 'Message' // Will be stored as 5 in DB
+	PAYMENT = 'Payment',
+	ASSIGNMENT = 'Assignment',
+	INVITATION = 'Invitation',
+	MENTION = 'Mention',
+	COMMENT = 'Comment',
+	MESSAGE = 'Message'
 }
packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.service.ts (1)

24-36: Enhance error handling with specific error types.

The current error handling catches all errors and converts them to HttpException with BAD_REQUEST status. Consider handling specific error types differently.

 async create(input: IUserNotificationSettingCreateInput): Promise<UserNotificationSetting> {
   try {
     const userId = input.userId || RequestContext.currentUserId();
     const tenantId = RequestContext.currentTenantId() || input.tenantId;

     return super.create({ ...input, userId, tenantId });
   } catch (error) {
-    throw new HttpException(
-      `Failed to create the notification setting: ${error.message}`,
-      HttpStatus.BAD_REQUEST
-    );
+    if (error instanceof TypeError || error instanceof ValidationError) {
+      throw new HttpException(
+        `Invalid notification setting data: ${error.message}`,
+        HttpStatus.BAD_REQUEST
+      );
+    }
+    throw new HttpException(
+      'Internal server error while creating notification setting',
+      HttpStatus.INTERNAL_SERVER_ERROR
+    );
   }
 }
packages/core/src/lib/shared/pipes/notification-type-transform.pipe.ts (2)

15-32: Consider using a map for enum-to-number conversion.

The switch statement implementation could be simplified using a mapping object for better maintainability.

+private static readonly enumToNumber = new Map<UserNotificationTypeEnum, number>([
+  [UserNotificationTypeEnum.PAYMENT, 0],
+  [UserNotificationTypeEnum.ASSIGNMENT, 1],
+  [UserNotificationTypeEnum.INVITATION, 2],
+  [UserNotificationTypeEnum.MENTION, 3],
+  [UserNotificationTypeEnum.COMMENT, 4],
+  [UserNotificationTypeEnum.MESSAGE, 5],
+]);

 to(value: UserNotificationTypeEnum): number {
-  switch (value) {
-    case UserNotificationTypeEnum.PAYMENT:
-      return 0;
-    case UserNotificationTypeEnum.ASSIGNMENT:
-      return 1;
-    case UserNotificationTypeEnum.INVITATION:
-      return 2;
-    case UserNotificationTypeEnum.MENTION:
-      return 3;
-    case UserNotificationTypeEnum.COMMENT:
-      return 4;
-    case UserNotificationTypeEnum.MESSAGE:
-      return 5;
-    default:
-      throw new Error(`Unknown notification type: ${value}`);
-  }
+  const number = UserNotificationTypeTransformerPipe.enumToNumber.get(value);
+  if (number === undefined) {
+    throw new Error(`Unknown notification type: ${value}`);
+  }
+  return number;
 }

40-57: Apply similar map-based approach for number-to-enum conversion.

Use the reverse mapping for consistency and maintainability.

+private static readonly numberToEnum = new Map<number, UserNotificationTypeEnum>(
+  Array.from(UserNotificationTypeTransformerPipe.enumToNumber.entries())
+    .map(([key, value]) => [value, key])
+);

 from(value: number): UserNotificationTypeEnum {
-  switch (value) {
-    case 0:
-      return UserNotificationTypeEnum.PAYMENT;
-    case 1:
-      return UserNotificationTypeEnum.ASSIGNMENT;
-    case 2:
-      return UserNotificationTypeEnum.INVITATION;
-    case 3:
-      return UserNotificationTypeEnum.MENTION;
-    case 4:
-      return UserNotificationTypeEnum.COMMENT;
-    case 5:
-      return UserNotificationTypeEnum.MESSAGE;
-    default:
-      throw new Error(`Unknown notification type value: ${value}`);
-  }
+  const enumValue = UserNotificationTypeTransformerPipe.numberToEnum.get(value);
+  if (enumValue === undefined) {
+    throw new Error(`Unknown notification type value: ${value}`);
+  }
+  return enumValue;
 }
packages/core/src/lib/user-notification/user-notification.controller.ts (1)

46-51: Pagination params not needed for single entity fetch.

The findById method includes pagination parameters which aren't typically needed when fetching a single entity by ID.

   async findById(
     @Param('id', UUIDValidationPipe) id: ID,
-    @Query() params: PaginationParams<UserNotification>
   ): Promise<UserNotification> {
-    return this.userNotificationService.findOneByIdString(id, params);
+    return this.userNotificationService.findOneByIdString(id);
   }
packages/contracts/src/lib/base-entity.model.ts (1)

63-66: Add JSDoc documentation for IBasePerEntityType interface.

The interface lacks documentation explaining its purpose and the significance of extending IBasePerTenantAndOrganizationEntityModel.

+/**
+ * Represents a base interface for entities that are associated with a specific entity type
+ * and belong to a tenant and organization.
+ *
+ * @extends IBasePerTenantAndOrganizationEntityModel
+ */
 export interface IBasePerEntityType extends IBasePerTenantAndOrganizationEntityModel {
   entityId: ID;
   entity: BaseEntityEnum;
 }
packages/core/src/lib/comment/comment.entity.ts (1)

7-8: LGTM! Improved entity inheritance structure.

The change to extend BasePerEntityType simplifies the entity hierarchy while maintaining the necessary functionality. This aligns with the broader refactoring of entity inheritance in the codebase.

Also applies to: 21-21

packages/core/src/lib/mention/mention.service.ts (1)

83-86: Consider implementing email notifications.

The TODO comment indicates a need for email notifications. This would enhance the user experience by providing multiple notification channels.

Would you like me to help implement the email notification functionality or create an issue to track this task?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0e05c2 and dfdc9ce.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (62)
  • nx.json (1 hunks)
  • packages/contracts/src/index.ts (2 hunks)
  • packages/contracts/src/lib/activity-log.model.ts (3 hunks)
  • packages/contracts/src/lib/base-entity.model.ts (1 hunks)
  • packages/contracts/src/lib/comment.model.ts (2 hunks)
  • packages/contracts/src/lib/employee-settings.model.ts (1 hunks)
  • packages/contracts/src/lib/favorite.model.ts (1 hunks)
  • packages/contracts/src/lib/mention.model.ts (2 hunks)
  • packages/contracts/src/lib/resource-link.model.ts (1 hunks)
  • packages/contracts/src/lib/subscription.model.ts (1 hunks)
  • packages/contracts/src/lib/user-notification-setting.model.ts (1 hunks)
  • packages/contracts/src/lib/user-notification.model.ts (1 hunks)
  • packages/core/src/lib/activity-log/activity-log.entity.ts (1 hunks)
  • packages/core/src/lib/app/app.module.ts (2 hunks)
  • packages/core/src/lib/comment/comment.entity.ts (2 hunks)
  • packages/core/src/lib/comment/comment.service.ts (1 hunks)
  • packages/core/src/lib/comment/dto/create-comment.dto.ts (2 hunks)
  • packages/core/src/lib/core/entities/entity-type-base.entity.ts (1 hunks)
  • packages/core/src/lib/core/entities/index.ts (2 hunks)
  • packages/core/src/lib/core/entities/internal.ts (3 hunks)
  • packages/core/src/lib/core/entities/subscribers/index.ts (2 hunks)
  • packages/core/src/lib/database/migrations/1738217979804-CreateUserNotificationTable.ts (1 hunks)
  • packages/core/src/lib/database/migrations/1738326053345-CreateUserNotificationSettingTable.ts (1 hunks)
  • packages/core/src/lib/favorite/favorite.entity.ts (1 hunks)
  • packages/core/src/lib/mention/mention.entity.ts (1 hunks)
  • packages/core/src/lib/mention/mention.module.ts (2 hunks)
  • packages/core/src/lib/mention/mention.service.ts (3 hunks)
  • packages/core/src/lib/resource-link/resource-link.entity.ts (1 hunks)
  • packages/core/src/lib/shared/pipes/index.ts (1 hunks)
  • packages/core/src/lib/shared/pipes/notification-type-transform.pipe.ts (1 hunks)
  • packages/core/src/lib/subscription/subscription.entity.ts (1 hunks)
  • packages/core/src/lib/tasks/commands/handlers/task-create.handler.ts (7 hunks)
  • packages/core/src/lib/tasks/screening-tasks/screening-tasks.service.ts (1 hunks)
  • packages/core/src/lib/tasks/task.module.ts (2 hunks)
  • packages/core/src/lib/tasks/task.service.ts (6 hunks)
  • packages/core/src/lib/user-notification/events/handlers/index.ts (1 hunks)
  • packages/core/src/lib/user-notification/events/handlers/user-notification.handler.ts (1 hunks)
  • packages/core/src/lib/user-notification/events/index.ts (1 hunks)
  • packages/core/src/lib/user-notification/events/user-notification.event.ts (1 hunks)
  • packages/core/src/lib/user-notification/repository/mikro-orm-user-notification.repository.ts (1 hunks)
  • packages/core/src/lib/user-notification/repository/type-orm-user-notification.repository.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/commands/handlers/index.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/commands/handlers/user-notification-setting.create.handler.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/commands/handlers/user-notification-setting.update.handler.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/commands/index.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/commands/user-notification-setting.create.command.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/commands/user-notification-setting.update.command.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/dto/create-user-notification-setting.dto.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/dto/index.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/dto/update-user-notification-setting.dto.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/repository/mikro-orm-user-notification-setting.repository.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/repository/type-orm-user-notification-setting.repository.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.controller.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.entity.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.module.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.service.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.subscriber.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification.controller.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification.entity.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification.helper.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification.module.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification.service.ts (1 hunks)
✅ Files skipped from review due to trivial changes (7)
  • packages/core/src/lib/user-notification/events/handlers/index.ts
  • packages/core/src/lib/shared/pipes/index.ts
  • packages/core/src/lib/user-notification/user-notification-setting/commands/index.ts
  • packages/core/src/lib/user-notification/events/index.ts
  • packages/contracts/src/lib/employee-settings.model.ts
  • packages/core/src/lib/user-notification/user-notification-setting/dto/index.ts
  • nx.json
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (63)
packages/core/src/lib/mention/mention.module.ts (1)

12-12: LGTM! Clean integration of UserNotificationModule.

The addition of UserNotificationModule is well-structured and follows the existing module organization pattern.

Let's verify the UserNotificationModule integration:

Also applies to: 22-22

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Description: Verify UserNotificationModule existence and integration

# Check if UserNotificationModule exists
echo "Checking UserNotificationModule existence..."
fd -e ts "user-notification.module.ts$"

# Check for any potential circular dependencies
echo "Checking for potential circular dependencies..."
rg -l "from.*mention" $(fd -e ts "user-notification")

Length of output: 2658


I'm generating an additional shell script to explicitly check if the integration introduced any circular dependency—specifically, whether the user-notification module is (unexpectedly) importing the mention module and vice versa.

Please run this script and share the results so we can confirm that the dependency integration is correct and that no circular dependency issues exist.


🏁 Script executed:

#!/bin/bash
# Check for any circular dependency between MentionModule and UserNotificationModule

echo "Searching for import of user-notification.module in mention/mention.module.ts"
rg "import.*user-notification\.module" packages/core/src/lib/mention/mention.module.ts

echo "Searching for import of mention.module in user-notification/user-notification.module.ts"
rg "import.*mention\.module" packages/core/src/lib/user-notification/user-notification.module.ts

Length of output: 625


UserNotificationModule Integration Verified

The UserNotificationModule is correctly imported into MentionModule, and there’s no evidence of a circular dependency (i.e., UserNotificationModule does not import MentionModule). The integration and module configuration are as expected.

packages/core/src/lib/subscription/subscription.entity.ts (2)

6-7: Verify removal of former entity references.
You've replaced "TenantOrganizationBaseEntity" with "BasePerEntityType" and presumably removed properties like "entityId" and "entity." Ensure that all references to those properties are either updated or removed throughout the codebase.


12-12: Confirm compatibility of Subscription with the new base class.
Switching to "BasePerEntityType" looks correct at first glance. Just confirm that inherited fields and logic (like ID handling and multi-tenant fields) still meet the requirements of Subscription scenarios.

packages/core/src/lib/resource-link/resource-link.entity.ts (2)

5-6: Cross-check removed validators or imports.
"IsEnum" and "IsUUID" were removed, along with "BaseEntityEnum." Verify no references rely on them and confirm that any replaced validations are still enforced.


8-13: Check for missing fields after changing base entity type.
Extending "BasePerEntityType" removes tenant/organization fields. If ResourceLink still needs multi-tenant or organizational context, consider reintroducing them or clarifying where that context is captured.

packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.entity.ts (4)

16-50: Evaluate default true booleans for optional notifications.
All notification-related fields ("payment", "assignment", "invitation", "mention", "comment", "message") default to true. Verify that this meets user expectations (e.g., might cause spammy notifications initially). You may want to handle default settings more dynamically.


52-56: Consider making preferences optional or providing a default.
"@isnotempty()" on "preferences" suggests it must always be provided, yet no default is assigned. This could cause errors if not supplied on creation. Assess whether a safe default or removing the "IsNotEmpty()" constraint would be better.


65-75: Revisit one-to-one ownership details.
By declaring this entity as the "owner" side of the relationship with a "cascade" on delete, removing the user will automatically remove notification settings. Confirm that this fits the desired domain model.


77-81: Ensure consistency between "user" and "userId" fields.
"creatorId" is optional in similar contexts, but here "userId" is a required ID. Check if that’s consistent with the rest of the system. If "user" is optional, its ID might need to be optional as well.

packages/core/src/lib/mention/mention.entity.ts (1)

7-7: Ensure all references to the new base class are updated consistently.
Switching to BasePerEntityType is fine, but verify that any references or assumptions tied to TenantOrganizationBaseEntity have been removed or updated (particularly around tenant or organization context).

packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.subscriber.ts (4)

6-7: Nice use of a dedicated subscriber.
This approach cleanly encapsulates entity lifecycle event logic for UserNotificationSetting.


46-48: Good practice to serialize data before insert.
Pre-serializing preferences for SQLite ensures consistency. Keep an eye on potential user input that might interfere with JSON structures.


57-59: Consistent pre-update handling.
Serializing preferences before updates mirrors the insert flow, preventing validation discrepancies.


69-83: Validate fallback handling on JSON parse errors.
The catch block resets preferences to an empty object on parsing errors. Verify that discarding invalid data is the intended approach, as it can silently lose user data.

packages/core/src/lib/user-notification/user-notification.entity.ts (4)

12-14: Clean inheritance approach.
Extending BasePerEntityType centralizes shared logic. Ensure the other fields that rely on tenant or organization context remain valid after this design shift.


34-39: Confirm enum storage strategy.
Storing the notification type as an integer is fine, but confirm it aligns with your usage patterns and that conversions in the code (e.g., from numeric to enum) are consistent.


74-95: Optional author references are well-structured.
The nullable relationship with sentBy is appropriate. Just confirm that any actions dependent on a valid author handle this field carefully.


100-118: Receiver relationship is properly indexed.
Storing receiverId with a relation index ensures efficient lookups. This should scale well for queries filtering user-specific notifications.

packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.controller.ts (2)

1-36: Consider specifying explicit permissions.
You have applied the TenantPermissionGuard and the @permissions() decorator without specifying any permissions. If the intention is to restrict or differentiate certain endpoints based on user roles or scopes, consider explicitly defining permissions to ensure that unauthorized access is properly blocked.


85-120: Ensure exceptions align with expected responses on update/delete.
The controller returns the updated or deleted record(s) but does not explicitly handle the case where the record might not exist. Verify that your service or command handlers throw NotFoundException or a meaningful error when a record is missing, so the correct HttpStatus.NOT_FOUND is returned.

packages/core/src/lib/database/migrations/1738326053345-CreateUserNotificationSettingTable.ts (2)

1-37: Check migration coverage in tests or CI.
Because this migration handles multiple database engines, verify through integration tests or pipeline checks that the up/down routines work correctly in each engine.


59-254: Migration logic appears correct.
The creation of unique indexes, foreign keys, and table structures for PostgreSQL, SQLite, and MySQL is well-structured for multi-DB support. Make sure to keep this file updated if future changes to user notification settings require altering the table schema.

packages/core/src/lib/database/migrations/1738217979804-CreateUserNotificationTable.ts (2)

60-74: Re-evaluate index usage.
There are many indexes on columns like isActive, isArchived, entityId, etc. While indexes can optimize specific queries, an overabundance could degrade write performance. Verify that each index is essential for common queries.


59-86: 🏁 Script executed:

#!/bin/bash
# Checking if pgcrypto extension is installed in Postgres.
# Adjust connection details as appropriate and run from the environment with psql.
psql -d your_database -c "CREATE EXTENSION IF NOT EXISTS pgcrypto;"

Length of output: 164

packages/contracts/src/lib/favorite.model.ts (1)

4-4: Verify removal of IBasePerTenantAndOrganizationEntityModel references.
By removing this interface from IFavorite, ensure that dependent code doesn’t rely on tenant or organization properties previously included.

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Searching references to the removed interface in the codebase.
fd --extension ts --exec rg "IBasePerTenantAndOrganizationEntityModel"

Length of output: 36870


Action: Confirm IFavorite no longer directly depends on IBasePerTenantAndOrganizationEntityModel

After reviewing the file in question, IFavorite now extends IEmployeeEntityInput and IBasePerEntityType rather than directly extending IBasePerTenantAndOrganizationEntityModel. A focused search in packages/contracts/src/lib/favorite.model.ts (using, for example, a grep for "IBasePerTenantAndOrganizationEntityModel") shows that the file no longer contains any direct reference or import of that interface. Although many other parts of the codebase still reference IBasePerTenantAndOrganizationEntityModel (as seen in the search output), there are no indications that code dependent on IFavorite expects it to extend the removed interface. In other words, any required tenant/organization properties—if still needed—should now be provided through the IBasePerEntityType abstraction, and no direct dependency on IBasePerTenantAndOrganizationEntityModel exists for favorites.

This change appears safe, and no dependent code requiring a direct reference to IBasePerTenantAndOrganizationEntityModel has been identified.

packages/core/src/lib/user-notification/repository/mikro-orm-user-notification.repository.ts (1)

1-4: LGTM! Clean and standard repository implementation.

The repository follows best practices by extending the base repository and properly typing it with the UserNotification entity.

packages/core/src/lib/user-notification/user-notification-setting/repository/mikro-orm-user-notification-setting.repository.ts (1)

1-4: LGTM! Clean and standard repository implementation.

The repository follows best practices by extending the base repository and properly typing it with the UserNotificationSetting entity.

packages/core/src/lib/user-notification/user-notification-setting/commands/handlers/index.ts (1)

1-4: LGTM! Clean command handlers organization.

The implementation follows best practices for organizing command handlers in a CQRS pattern.

packages/core/src/lib/user-notification/user-notification-setting/dto/update-user-notification-setting.dto.ts (1)

8-10: LGTM! Well-structured DTO implementation.

The DTO correctly uses NestJS utility types to create a partial update type while omitting sensitive fields. Good use of documentation.

packages/core/src/lib/user-notification/user-notification-setting/repository/type-orm-user-notification-setting.repository.ts (1)

1-11: LGTM! Clean implementation following TypeORM and NestJS patterns.

The repository implementation correctly follows standard patterns:

  • Proper use of dependency injection
  • Clean extension of TypeORM's Repository class
  • Correct super call with required parameters
packages/contracts/src/lib/subscription.model.ts (1)

1-1: LGTM! Clean inheritance refactoring.

The simplified inheritance chain is valid since IBasePerEntityType now includes tenant/organization properties.

Also applies to: 4-4

packages/contracts/src/lib/resource-link.model.ts (1)

2-2: LGTM! Clean inheritance refactoring.

The simplified inheritance chain is valid since IBasePerEntityType now includes tenant/organization properties.

Also applies to: 5-5

packages/contracts/src/lib/mention.model.ts (2)

4-11: LGTM! Interface simplification improves maintainability.

The removal of IBasePerTenantAndOrganizationEntityModel inheritance in favor of IBasePerEntityType aligns with the broader refactoring effort and reduces interface complexity.


13-15: LGTM! Enhanced input interface with optional entity name.

The addition of the optional entityName property to IMentionCreateInput maintains consistency with similar changes in other interfaces.

packages/core/src/lib/comment/dto/create-comment.dto.ts (1)

16-22: LGTM! Well-structured DTO with proper validation.

The addition of entityName property with appropriate validation decorators (@IsOptional, @IsString) and API documentation (@ApiPropertyOptional) ensures type safety and maintainability.

packages/core/src/lib/user-notification/events/handlers/user-notification.handler.ts (1)

5-19: LGTM! Well-implemented CQRS event handler.

The implementation follows best practices:

  • Proper use of dependency injection
  • Clear documentation
  • Single responsibility principle
  • Async/await for service call
packages/core/src/lib/core/entities/entity-type-base.entity.ts (2)

8-18: LGTM! Well-structured base class with proper validation for entity type.

The entity property implementation includes:

  • Clear documentation
  • Proper validation with @IsNotEmpty and @IsEnum
  • Database indexing with @ColumnIndex
  • ORM compatibility with @MultiORMColumn

19-28: LGTM! Well-structured base class with proper validation for entity ID.

The entityId property implementation includes:

  • Clear documentation
  • Proper validation with @IsNotEmpty and @IsUUID
  • Database indexing with @ColumnIndex
  • ORM compatibility with @MultiORMColumn
packages/core/src/lib/user-notification/user-notification-setting/commands/handlers/user-notification-setting.create.handler.ts (1)

1-20: LGTM! Well-structured command handler implementation.

The implementation follows CQRS best practices with proper dependency injection and clear documentation.

packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.module.ts (1)

14-15: Verify the necessity of dual ORM configuration.

The module is configured to use both TypeORM and MikroORM simultaneously. This could lead to:

  • Increased complexity in managing database operations
  • Potential data inconsistencies
  • Higher maintenance overhead

Please confirm if this dual setup is intentional and necessary.

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Search for other modules using both ORMs to verify if this is a pattern
echo "Searching for modules using both TypeOrmModule and MikroOrmModule..."
rg "TypeOrmModule.forFeature|MikroOrmModule.forFeature" -A 5 -B 5

Length of output: 65862


Dual ORM Configuration Confirmed as Intentional

The codebase consistently applies both TypeORM and MikroORM across numerous modules (e.g., GitHub, changelog, wakatime, proposals, etc.). This pattern indicates that the dual ORM setup is intentional and part of the overall architectural design.

  • The user-notification-setting module aligns with similar configurations elsewhere.
  • This practice is consistently applied, suggesting a deliberate design choice rather than an oversight.
packages/core/src/lib/user-notification/user-notification.module.ts (2)

15-16: Verify the necessity of dual ORM configuration.

Similar to the settings module, this module also uses both TypeORM and MikroORM. Please confirm if this dual setup is required.


13-24: LGTM! Well-structured module configuration.

The module is well-organized with appropriate imports, providers, and exports. The integration with role permissions and notification settings is properly configured.

packages/contracts/src/lib/comment.model.ts (2)

7-7: LGTM! Simplified interface inheritance.

The removal of IBasePerTenantAndOrganizationEntityModel aligns with the broader refactoring effort to streamline entity models.


24-30: LGTM! Added entityName for notification support.

The addition of the optional entityName property enables better context in notifications when comments are created.

packages/core/src/lib/favorite/favorite.entity.ts (1)

1-12: LGTM! Simplified entity inheritance.

The changes align with the broader refactoring effort:

  • Switched to BasePerEntityType
  • Removed redundant properties
  • Updated imports appropriately
packages/core/src/lib/tasks/task.module.ts (1)

19-19: LGTM! Verify notification handling in tasks.

The UserNotificationModule integration looks correct. Ensure that task-related notifications are properly triggered in the TaskService and handlers.

Also applies to: 32-32

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Check if TaskService properly utilizes UserNotificationService
ast-grep --pattern 'class TaskService {
  $$$
  constructor($$$) {
    $$$
    private readonly userNotificationService: UserNotificationService
    $$$
  }
  $$$
}'

Length of output: 167


I'm not seeing an output from the initial AST search. Let's gather more evidence to ensure TaskService is properly triggering notifications. I'll run a script to search for direct references to "userNotificationService" in TaskService and associated files.

We'll use the output of this script to verify that TaskService is properly utilizing the notification service.


🏁 Script executed:

#!/bin/bash
# Search for usage of "this.userNotificationService" in files related to task logic.
rg "this\.userNotificationService" -n -C 5 .

Length of output: 7167


Notification handling in tasks appears properly integrated.

Our grep investigation confirms that the TaskService (in packages/core/src/lib/tasks/task.service.ts) and the task create handler (in packages/core/src/lib/tasks/commands/handlers/task-create.handler.ts) both invoke the userNotificationService.publishNotificationEvent method for task-related events. This verifies that task-related notifications are triggered as expected.

packages/contracts/src/lib/activity-log.model.ts (1)

11-11: Verify impact of removing tenant/organization base model.

The removal of IBasePerTenantAndOrganizationEntityModel might affect tenant isolation. Ensure that tenant/organization scoping is handled appropriately through IBasePerEntityType.

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Check if IBasePerEntityType includes tenant/organization fields
ast-grep --pattern 'interface IBasePerEntityType {
  $$$
  tenantId?: $_;
  organizationId?: $_;
  $$$
}'

Length of output: 107


I'm not seeing evidence from the previous script. Let's run a more relaxed search to explicitly check if the IBasePerEntityType interface includes tenantId and organizationId definitions. We'll search for these fields within the interface block.


🏁 Script executed:

#!/bin/bash
echo "Searching for tenant/organization fields in IBasePerEntityType interface:"
rg -n "interface IBasePerEntityType" -A 50 | grep -E "(tenantId\?:|organizationId\?:)"

Length of output: 245


Let's verify whether references to the removed IBasePerTenantAndOrganizationEntityModel are still present in the codebase, to better understand the impact of its removal.


🏁 Script executed:

#!/bin/bash
# Search for any references to IBasePerTenantAndOrganizationEntityModel in the entire repository.
rg -n "IBasePerTenantAndOrganizationEntityModel"

Length of output: 62861


Tenant/Organization scoping remains intact.

The investigation shows that IBasePerEntityType extends IBasePerTenantAndOrganizationEntityModel (as seen in packages/contracts/src/lib/base-entity.model.ts near line 63), which means that tenantId and organizationId are still part of the inheritance chain for IActivityLog. This removal does not compromise the tenant/organization scoping since the necessary fields continue to be inherited.

packages/core/src/lib/core/entities/subscribers/index.ts (1)

49-50: LGTM! Export order matches array order.

The export order of subscribers matches their order in the coreSubscribers array, maintaining consistency.

packages/core/src/lib/activity-log/activity-log.entity.ts (1)

14-14: LGTM! Proper inheritance from BasePerEntityType.

The class correctly extends BasePerEntityType and implements IActivityLog, maintaining proper type safety.

packages/core/src/lib/comment/comment.service.ts (1)

69-70: LGTM! Enhanced mention publishing with entity name.

The addition of entityName to the mention publishing process enhances the context provided for notifications.

packages/core/src/lib/mention/mention.service.ts (2)

4-12: LGTM! Well-structured notification system integration.

The addition of UserNotificationService and related enums sets up a proper foundation for the notification system.

Also applies to: 20-20, 27-27


67-82: LGTM! Comprehensive notification event publishing.

The implementation properly handles all necessary details for notification publishing:

  • Entity context
  • User information
  • Organization and tenant context
  • Action type and user display name
packages/core/src/lib/core/entities/index.ts (1)

153-154: LGTM! Proper integration of notification entities.

The UserNotification and UserNotificationSetting entities are correctly added to both imports and exports, maintaining consistency in the core entities system.

Also applies to: 313-314

packages/contracts/src/index.ts (1)

145-146: LGTM! New notification model exports added.

The new exports for user notification models are correctly placed and follow the existing pattern.

packages/core/src/lib/tasks/commands/handlers/task-create.handler.ts (4)

10-12: LGTM! Notification-related imports added.

The new imports for notification enums are correctly placed and necessary for the notification functionality.


40-41: LGTM! User notification service properly injected.

The service is correctly injected in the constructor following dependency injection best practices.


59-60: LGTM! User context retrieval added.

Properly retrieving the current user context for notification purposes.


154-167: LGTM! Notification publishing logic implemented.

The notification publishing logic is well-structured with all required parameters:

  • Correct entity type and ID
  • Proper notification type for assignments
  • Includes sender and receiver IDs
  • Includes task title and user name for context
packages/core/src/lib/tasks/screening-tasks/screening-tasks.service.ts (1)

102-103: LGTM! Entity name added to mention publishing.

The addition of entityName parameter enhances the mention functionality by providing task context.

packages/core/src/lib/core/entities/internal.ts (1)

6-6: LGTM! Notification-related exports added.

The new exports are properly organized:

  • Base entity type export with other base entities
  • User notification entities with other core entities
  • Notification setting subscriber with other subscribers

Also applies to: 159-160, 212-212

packages/core/src/lib/app/app.module.ts (1)

165-166: LGTM! Module imports are correctly added.

The UserNotificationModule and UserNotificationSettingModule are properly imported and added to the module's imports array.

Also applies to: 475-476

packages/core/src/lib/tasks/task.service.ts (2)

31-33: LGTM! Required imports are correctly added.

The necessary enums and service for user notifications are properly imported.

Also applies to: 51-51


63-64: LGTM! Dependency injection is properly implemented.

The UserNotificationService is correctly injected following the established pattern.

@evereq
Copy link
Member

evereq commented Feb 8, 2025

@GloireMutaliko21 please review coderabbit suggestions!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/core/src/lib/user-notification/user-notification.helper.ts (1)

3-10: ⚠️ Potential issue

Fix inconsistencies in notification templates.

There are several issues in the templates:

  1. Inconsistent placeholder usage: The templates use {userName} while some might expect {user}.
  2. The "Messaged" template has an extra quote character at the end.

Apply this diff to fix the issues:

 const UserNotificationTemplates = {
 	[NotificationActionTypeEnum.Paid]: `You have been {action}`,
 	[NotificationActionTypeEnum.Commented]: `{userName} {action} on {entity} "{entityName}"`,
 	[NotificationActionTypeEnum.Assigned]: `{userName} {action} you to the {entity} "{entityName}"`,
 	[NotificationActionTypeEnum.Invited]: `{userName} {action} you to join the {entity} "{entityName}"`,
 	[NotificationActionTypeEnum.Mentioned]: `{userName} {action} you on the {entity} "{entityName}"`,
-	[NotificationActionTypeEnum.Messaged]: `{userName} {action} you a new message"`
+	[NotificationActionTypeEnum.Messaged]: `{userName} {action} you a new message`
 };
🧹 Nitpick comments (3)
packages/core/src/lib/user-notification/user-notification.helper.ts (1)

12-36: Consider enhancing error handling in the template processor.

The function silently returns an empty string for unknown placeholders, which might hide template issues.

Consider throwing an error for unknown placeholders:

 export function generateNotificationTitle(
 	action: NotificationActionTypeEnum,
 	entity: BaseEntityEnum,
 	entityName: string,
 	userName: string
 ) {
 	const template = UserNotificationTemplates[action];
 	return template.replace(/\{(\w+)\}/g, (_, key) => {
 		switch (key) {
 			case 'action':
 				return action;
 			case 'entity':
 				return entity;
 			case 'entityName':
 				return entityName;
 			case 'userName':
 				return userName;
 			default:
-				return '';
+				throw new Error(`Unknown placeholder: {${key}}`);
 		}
 	});
 }
packages/core/src/lib/user-notification/user-notification.service.ts (2)

89-103: Improve error handling in markAllAsRead method.

The method should handle the case where no user ID is available in the request context.

Apply this change:

 async markAllAsRead(): Promise<any> {
   try {
     const userId = RequestContext.currentUserId();
+    if (!userId) {
+      throw new BadRequestException('User ID not found in request context');
+    }
     const readAt = new Date();
     return await super.update(
       { isRead: false, isArchived: false, receiverId: userId },
       { isRead: true, readAt }
     );
   } catch (error) {
     throw new BadRequestException('Error while updating notifications', error);
   }
 }

135-155: Consider using a Map for notification type mapping.

The switch statement could be replaced with a Map for better maintainability and performance.

Consider this alternative implementation:

+private readonly notificationTypeMap = new Map<UserNotificationTypeEnum, (settings: IUserNotificationSetting) => boolean>([
+  [UserNotificationTypeEnum.PAYMENT, (settings) => settings.payment ?? true],
+  [UserNotificationTypeEnum.ASSIGNMENT, (settings) => settings.assignment ?? true],
+  [UserNotificationTypeEnum.INVITATION, (settings) => settings.invitation ?? true],
+  [UserNotificationTypeEnum.MENTION, (settings) => settings.mention ?? true],
+  [UserNotificationTypeEnum.COMMENT, (settings) => settings.comment ?? true],
+  [UserNotificationTypeEnum.MESSAGE, (settings) => settings.message ?? true],
+]);
+
 private shouldCreateUserNotification(
   userNotificationSetting: IUserNotificationSetting,
   type: UserNotificationTypeEnum
 ): boolean {
-  switch (type) {
-    case UserNotificationTypeEnum.PAYMENT:
-      return userNotificationSetting.payment ?? true;
-    case UserNotificationTypeEnum.ASSIGNMENT:
-      return userNotificationSetting.assignment ?? true;
-    case UserNotificationTypeEnum.INVITATION:
-      return userNotificationSetting.invitation ?? true;
-    case UserNotificationTypeEnum.MENTION:
-      return userNotificationSetting.mention ?? true;
-    case UserNotificationTypeEnum.COMMENT:
-      return userNotificationSetting.comment ?? true;
-    case UserNotificationTypeEnum.MESSAGE:
-      return userNotificationSetting.message ?? true;
-    default:
-      return false;
-  }
+  const handler = this.notificationTypeMap.get(type);
+  return handler ? handler(userNotificationSetting) : false;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dfdc9ce and 338bd73.

📒 Files selected for processing (2)
  • packages/core/src/lib/user-notification/user-notification.helper.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification.service.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: test
  • GitHub Check: build
🔇 Additional comments (1)
packages/core/src/lib/user-notification/user-notification.service.ts (1)

37-81: ⚠️ Potential issue

Fix return type mismatch and improve error handling.

  1. The method returns undefined when notification is not allowed, but the return type is Promise<IUserNotification>.
  2. Error logging should use a proper logging service instead of console.log.

Apply these changes:

-async create(input: IUserNotificationCreateInput): Promise<IUserNotification> {
+async create(input: IUserNotificationCreateInput): Promise<IUserNotification | undefined> {
   try {
     const tenantId = RequestContext.currentTenantId() || input.tenantId;
     let userSetting: IUserNotificationSetting;
     try {
       userSetting = await this.userNotificationSettingService.findOneByWhereOptions({
         userId: input.receiverId,
         tenantId,
         organizationId: input.organizationId
       });
     } catch (error) {
       if (error instanceof NotFoundException) {
         userSetting = await this.userNotificationSettingService.create({
           userId: input.receiverId,
           assignment: true,
           comment: true,
           invitation: true,
           mention: true,
           message: true,
           payment: true,
           preferences: {
             email: true,
             inApp: true
           },
           organizationId: input.organizationId,
           tenantId
         });
       }
     }
     const isAllowedNotification = this.shouldCreateUserNotification(userSetting, input.type);
     if (!isAllowedNotification) {
-      return;
+      return undefined;
     }
     return await super.create({ ...input, tenantId });
   } catch (error) {
-    console.log('Error while creating notification:', error);
+    this.logger.error('Error while creating notification:', error);
     throw new BadRequestException('Error while creating notification', error);
   }
 }

Likely invalid or redundant comment.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
packages/core/src/lib/user-notification/user-notification.service.ts (2)

89-102: Improve error handling and response in markAllAsRead.

  1. The method returns a hardcoded success message.
  2. Error handling could be more informative.

Apply this diff to improve the implementation:

-			return { message: 'successful' };
+			return { message: 'All notifications marked as read', count: result.affected };
-			throw new BadRequestException('Error while updating notifications', error);
+			throw new BadRequestException(error.message || 'Error while updating notifications');

134-154: Improve default case handling in shouldCreateUserNotification.

The default case returns false without any explanation, which could make debugging difficult.

Apply this diff to improve error handling:

-				return false;
+				console.warn(`Unknown notification type: ${type}`);
+				return false;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 338bd73 and c23329a.

📒 Files selected for processing (3)
  • packages/contracts/src/lib/user-notification.model.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification.helper.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification.service.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/contracts/src/lib/user-notification.model.ts
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: build
  • GitHub Check: test
🔇 Additional comments (2)
packages/core/src/lib/user-notification/user-notification.helper.ts (1)

3-10: ⚠️ Potential issue

Fix inconsistency in the "Messaged" template.

The "Messaged" template has a different format and an extra quote character compared to other templates.

Apply this diff to maintain consistency:

-	[NotificationActionTypeEnum.Messaged]: `{userName} sent you a new message"`
+	[NotificationActionTypeEnum.Messaged]: `{userName} {action} you a new message`

Likely invalid or redundant comment.

packages/core/src/lib/user-notification/user-notification.service.ts (1)

112-125: LGTM!

The method is well-documented and follows the single responsibility principle.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
packages/core/src/lib/user-notification/pipes/notification-type-transform.pipe.ts (2)

15-32: Consider enhancing type safety and maintainability.

While the implementation is functional, consider these improvements:

  1. Define the integer mappings as constants to avoid magic numbers
  2. Add type safety for future enum additions

Here's a suggested implementation:

+const NOTIFICATION_TYPE_MAPPING = {
+  [UserNotificationTypeEnum.PAYMENT]: 0,
+  [UserNotificationTypeEnum.ASSIGNMENT]: 1,
+  [UserNotificationTypeEnum.INVITATION]: 2,
+  [UserNotificationTypeEnum.MENTION]: 3,
+  [UserNotificationTypeEnum.COMMENT]: 4,
+  [UserNotificationTypeEnum.MESSAGE]: 5,
+} as const;
+
+type NotificationTypeValues = typeof NOTIFICATION_TYPE_MAPPING[keyof typeof NOTIFICATION_TYPE_MAPPING];
+
 to(value: UserNotificationTypeEnum): number {
-  switch (value) {
-    case UserNotificationTypeEnum.PAYMENT:
-      return 0;
-    case UserNotificationTypeEnum.ASSIGNMENT:
-      return 1;
-    case UserNotificationTypeEnum.INVITATION:
-      return 2;
-    case UserNotificationTypeEnum.MENTION:
-      return 3;
-    case UserNotificationTypeEnum.COMMENT:
-      return 4;
-    case UserNotificationTypeEnum.MESSAGE:
-      return 5;
-    default:
-      throw new Error(`Unknown notification type: ${value}`);
+  const mappedValue = NOTIFICATION_TYPE_MAPPING[value];
+  if (mappedValue === undefined) {
+    throw new Error(`Invalid notification type: ${value}. Expected one of: ${Object.keys(NOTIFICATION_TYPE_MAPPING).join(', ')}`);
   }
+  return mappedValue;
 }

40-57: Refactor to use the same mapping for bidirectional conversion.

The from method can be simplified by using the same constant mapping as the to method, making the code more maintainable.

Here's a suggested implementation that complements the previous changes:

 from(value: number): UserNotificationTypeEnum {
-  switch (value) {
-    case 0:
-      return UserNotificationTypeEnum.PAYMENT;
-    case 1:
-      return UserNotificationTypeEnum.ASSIGNMENT;
-    case 2:
-      return UserNotificationTypeEnum.INVITATION;
-    case 3:
-      return UserNotificationTypeEnum.MENTION;
-    case 4:
-      return UserNotificationTypeEnum.COMMENT;
-    case 5:
-      return UserNotificationTypeEnum.MESSAGE;
-    default:
-      throw new Error(`Unknown notification type value: ${value}`);
+  const entry = Object.entries(NOTIFICATION_TYPE_MAPPING).find(([_, val]) => val === value);
+  if (!entry) {
+    throw new Error(`Invalid notification type value: ${value}. Expected one of: ${Object.values(NOTIFICATION_TYPE_MAPPING).join(', ')}`);
   }
+  return entry[0] as UserNotificationTypeEnum;
 }
packages/core/src/lib/subscription/subscription.service.ts (1)

57-58: Consider implementing the optional notification feature.

There's a TODO comment about optional subscription notifications. Since this PR is about internal system notifications, this might be a good opportunity to implement this feature.

Would you like me to help implement the subscription notification feature or create an issue to track this task?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a17bdd and d3ced5b.

📒 Files selected for processing (23)
  • packages/contracts/src/index.ts (2 hunks)
  • packages/contracts/src/lib/subscription.model.ts (2 hunks)
  • packages/contracts/src/lib/user-notification-setting.model.ts (1 hunks)
  • packages/core/src/lib/core/entities/index.ts (2 hunks)
  • packages/core/src/lib/core/entities/internal.ts (3 hunks)
  • packages/core/src/lib/subscription/commands/handlers/subscription.create.handler.ts (2 hunks)
  • packages/core/src/lib/subscription/commands/subscription.create.command.ts (1 hunks)
  • packages/core/src/lib/subscription/dto/create-subscription.dto.ts (1 hunks)
  • packages/core/src/lib/subscription/dto/subscription-find-input.dto.ts (1 hunks)
  • packages/core/src/lib/subscription/events/handlers/subscription.create.handler.ts (2 hunks)
  • packages/core/src/lib/subscription/events/subscription.create.event.ts (1 hunks)
  • packages/core/src/lib/subscription/subscription.controller.ts (3 hunks)
  • packages/core/src/lib/subscription/subscription.entity.ts (1 hunks)
  • packages/core/src/lib/subscription/subscription.service.ts (3 hunks)
  • packages/core/src/lib/user-notification/events/handlers/index.ts (1 hunks)
  • packages/core/src/lib/user-notification/events/handlers/user-notification.handler.ts (1 hunks)
  • packages/core/src/lib/user-notification/events/user-notification.event.ts (1 hunks)
  • packages/core/src/lib/user-notification/pipes/index.ts (1 hunks)
  • packages/core/src/lib/user-notification/pipes/notification-type-transform.pipe.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/dto/create-user-notification-setting.dto.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.controller.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification.entity.ts (1 hunks)
  • packages/core/src/lib/user-notification/user-notification.service.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/core/src/lib/user-notification/pipes/index.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • packages/core/src/lib/user-notification/events/handlers/index.ts
  • packages/core/src/lib/core/entities/index.ts
  • packages/core/src/lib/user-notification/events/user-notification.event.ts
  • packages/core/src/lib/user-notification/user-notification-setting/user-notification-setting.controller.ts
  • packages/core/src/lib/user-notification/user-notification.entity.ts
  • packages/contracts/src/lib/user-notification-setting.model.ts
  • packages/core/src/lib/user-notification/user-notification.service.ts
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: test
🔇 Additional comments (20)
packages/contracts/src/index.ts (2)

146-147: LGTM! New notification models are correctly exported.

The new exports for user notification models are properly placed and maintain consistency with the existing export pattern.


161-162: LGTM! Base entity exports are properly updated.

The addition of IBasePerEntityType export and the trailing comma improvement maintain good code organization.

packages/core/src/lib/user-notification/user-notification-setting/dto/create-user-notification-setting.dto.ts (2)

1-4: LGTM! Imports are well-organized and necessary.

The imports follow a logical organization pattern and each import serves a clear purpose in the implementation.


6-11: LGTM! Well-structured DTO implementation.

The DTO correctly:

  • Combines base DTOs using IntersectionType
  • Excludes user-related fields as previously requested
  • Implements the contract interface
packages/core/src/lib/core/entities/internal.ts (1)

6-6: LGTM! New exports are well-organized.

The new exports for user notification entities and subscriber are properly placed in their respective sections and follow the established naming conventions.

Let's verify the implementation of these new entities and subscriber:

Also applies to: 160-161, 213-213

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Description: Verify the existence and basic structure of the new notification-related files

# Check for entity-type-base.entity
echo "Checking entity-type-base.entity..."
fd "entity-type-base.entity.ts$"

# Check for user notification entities
echo "Checking user notification entities..."
fd "user-notification.entity.ts$"
fd "user-notification-setting.entity.ts$"

# Check for user notification subscriber
echo "Checking user notification subscriber..."
fd "user-notification-setting.subscriber.ts$"

# Verify basic structure of the entities
echo "Checking entity implementations..."
for file in $(fd -t f "(entity-type-base|user-notification|user-notification-setting)\.(entity|subscriber)\.ts$"); do
  echo "=== Content of $file ==="
  cat "$file"
done

Length of output: 13372


LGTM! All new exports have been verified.

  • The export in the barrel file is correctly updated.
  • The files for entity-type-base.entity, user-notification.entity, user-notification-setting.entity, and user-notification-setting.subscriber exist in the expected directories.
  • Their implementations align with the project’s naming conventions and structure.
packages/core/src/lib/user-notification/events/handlers/user-notification.handler.ts (2)

1-4: LGTM! Clean and well-organized imports.

The imports are properly organized, following the convention of external dependencies first, followed by internal modules.


5-7: LGTM! Well-structured event handler class.

The class follows NestJS best practices with proper dependency injection and event handler implementation. Good use of the readonly modifier for immutability.

packages/core/src/lib/user-notification/pipes/notification-type-transform.pipe.ts (2)

1-8: Well-structured class with clear documentation!

The class follows Angular's pipe naming convention and is well-documented with clear JSDoc comments explaining its purpose.


1-58: Verify enum values and module registration.

Please ensure:

  1. The enum values in UserNotificationTypeEnum match these mappings
  2. The pipe is properly registered in the UserNotificationModule
✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Check enum values in contracts
rg -A 10 "export enum UserNotificationTypeEnum" 

# Check module registration
rg "UserNotificationTypeTransformerPipe" -A 5 -B 5

Length of output: 5446


Enum mappings and transformer integration verified.

  • The enum values in UserNotificationTypeEnum correctly match the expected mappings.
  • The transformer is instantiated within the entity (via the MultiORMColumn decorator in user-notification.entity.ts), confirming its integration with the user notification system.
packages/core/src/lib/subscription/events/subscription.create.event.ts (1)

1-6: LGTM! Interface update is consistent with the refactoring.

The change from ISubscriptionCreateInput to IEntitySubscriptionCreateInput maintains type safety while aligning with the broader interface renaming pattern.

packages/core/src/lib/subscription/dto/subscription-find-input.dto.ts (1)

1-5: LGTM! DTO update maintains type safety.

The change from ISubscriptionFindInput to IEntitySubscriptionFindInput is consistent with the refactoring while preserving the existing inheritance structure.

packages/core/src/lib/subscription/commands/subscription.create.command.ts (1)

1-8: LGTM! Command interface update is consistent.

The change from ISubscriptionCreateInput to IEntitySubscriptionCreateInput maintains the command pattern while aligning with the interface renaming.

packages/core/src/lib/subscription/dto/create-subscription.dto.ts (1)

9-11: Verify omitted properties after interface change.

While the change from ISubscriptionCreateInput to IEntitySubscriptionCreateInput is consistent, please verify that omitting 'userId' and 'user' properties is still valid with the new interface.

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Search for the interface definition to verify omitted properties
ast-grep --pattern 'interface IEntitySubscriptionCreateInput {
  $$$
}'

Length of output: 73


I'm not seeing the interface definition for IEntitySubscriptionCreateInput with the initial AST query. It appears that the interface might be defined using a different pattern (or as a type alias) that our AST query didn't catch. Before drawing a conclusion about the validity of omitting the properties, we should verify how IEntitySubscriptionCreateInput is defined and whether it indeed includes (or excludes) the 'userId' and 'user' properties.

Let's gather additional information by searching for the export of IEntitySubscriptionCreateInput using a general regex search. Please run the following script:

If this search still yields no results or if the definition is unclear, a manual verification of the interface's definition will be necessary to confirm that omitting 'userId' and 'user' remains valid.


🏁 Script executed:

#!/bin/bash
rg -e "export (interface|type) IEntitySubscriptionCreateInput" -n .

Length of output: 293


I'll now gather additional context from the definition of IEntitySubscriptionCreateInput to see if it includes the properties 'userId' and 'user'. Please run the following shell script to output the surrounding lines of the interface:


🏁 Script executed:

#!/bin/bash
rg -A 20 "export interface IEntitySubscriptionCreateInput" -n packages/contracts/src/lib/subscription.model.ts

Length of output: 489


Omission of 'user' and 'userId' is Valid Per the New Interface.

The interface IEntitySubscriptionCreateInput (defined in packages/contracts/src/lib/subscription.model.ts at line 18) extends:

  • Omit<IEntitySubscription, 'user' | 'userId'> — excluding both user and userId
  • Partial<Pick<IEntitySubscription, 'userId'>> — reintroducing userId as an optional property

This means that omitting both properties in the DTO via:

OmitType(Subscription, ['userId', 'user'])

is consistent with the expected structure, as the interface does not mandate userId (it is optional) and completely omits user.

packages/core/src/lib/subscription/commands/handlers/subscription.create.handler.ts (1)

1-1: LGTM! Interface updates are consistent with the broader refactoring.

The changes correctly update the import and return type from ISubscription to IEntitySubscription while maintaining the same handler logic.

Also applies to: 10-10

packages/contracts/src/lib/subscription.model.ts (1)

1-1: LGTM! Interface updates simplify the model structure.

The changes correctly:

  • Remove the tenant/organization base model dependency
  • Rename interfaces to include "Entity" prefix
  • Maintain type consistency across the model

Also applies to: 4-4, 18-22

packages/core/src/lib/subscription/events/handlers/subscription.create.handler.ts (1)

2-2: LGTM! Handler and documentation updates are consistent.

The changes correctly update both the implementation and documentation to use IEntitySubscription.

Also applies to: 14-14, 17-17

packages/core/src/lib/subscription/subscription.entity.ts (2)

11-12: Rename class to EntitySubscription as previously requested.

As discussed in previous reviews, please rename the class to EntitySubscription to maintain consistency with the new naming convention.


11-11: Verify table name update in migrations.

Since the table name will be renamed to entity_subscription, please ensure that:

  1. A migration file exists for this table rename
  2. The entity decorator is updated accordingly
❌ Verification inconclusive

🏁 Script executed:

#!/bin/bash
# Check for migration files containing table rename
rg -l "entity_subscription" packages/core/src/database/migrations/

Length of output: 145


I'll run another command to search the entire repository for any migration file reference to the new table name (entity_subscription) using a likely SQL phrase (e.g., a RENAME TO clause):


🏁 Script executed:

#!/bin/bash
rg -l "RENAME TO entity_subscription" .

Length of output: 41


Action Required: Migration Update and Entity Decorator Inconsistency

Our searches for any migration file indicating a rename to entity_subscription (via patterns like "entity_subscription" and "RENAME TO entity_subscription") returned no evidence of such a migration. Additionally, the entity decorator still uses 'subscription' rather than the expected new table name of 'entity_subscription'.

  • Migration File: There is no migration script that renames the table to entity_subscription.
  • Entity Decorator: The decorator remains unchanged (@MultiORMEntity('subscription', ...)) instead of reflecting the new table name.

Please verify and update:

  1. Add or update a migration file to rename the table from subscription to entity_subscription.
  2. Update the entity decorator to use 'entity_subscription' accordingly.
packages/core/src/lib/subscription/subscription.controller.ts (1)

5-5: LGTM! Interface renaming changes are consistent.

The changes correctly update the return types to use the new IEntitySubscription interface, maintaining consistency with the broader refactoring effort across the codebase.

Also applies to: 36-36, 70-70

packages/core/src/lib/subscription/subscription.service.ts (1)

2-7: LGTM! Interface renaming changes are consistent.

The changes correctly update the imports, method signatures, and JSDoc comments to use the new interface names, maintaining consistency with the broader refactoring effort across the codebase.

Also applies to: 27-31, 71-71, 78-78

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (24)
nx.json (1)

173-179: Nitpick: Consider Reassessing the "defaultBase" Value

The final configuration settings, including "useInferencePlugins", "defaultBase", and "release", are standard. Note that "defaultBase" is set to "master". If your repository has migrated to using "main", it might be prudent to update this value for consistency.

packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.subscriber.ts (2)

23-37: Consider using a structured logger instead of console.error.

Here, the error is currently being logged using console.error(error). Using a more structured logging framework (e.g., the NestJS logger) can help with better log formatting and maintain consistent logging across services. This also helps ensure sensitive data isn’t inadvertently printed to stdout.

- console.error(error);
+ Logger.error(error.message, error.stack, 'EmployeeNotificationSettingSubscriber');

69-83: Validate the structure of parsed preferences.

After parsing, it might be valuable to verify that the parsed object adheres to expected properties or structure, especially since errors are recovered by setting preferences to an empty object.

packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.controller.ts (3)

27-29: Clarify or customize permissions.

You are using @UseGuards(TenantPermissionGuard, PermissionGuard) and @Permissions() without specifying explicit permissions or roles. It may be helpful to define relevant permission keys for improved clarity and maintainability of access control.


77-83: Add error handling for not found records.

Although findOneByIdString can throw an error or return undefined if the record is not found, the code does not explicitly handle that scenario. Consider throwing an HTTP exception when the record is not found to return the correct HTTP 404 status.

const entity = await this.employeeNotificationSettingService.findOneByIdString(id, params);
- return entity;
+ if (!entity) {
+   throw new NotFoundException(`EmployeeNotificationSetting with ID ${id} not found`);
+ }
+ return entity;

145-147: Consider returning a custom response or status.

Returning DeleteResult directly might leak low-level details (e.g., how many records were deleted). It can be beneficial to return a more semantically relevant response object or HttpStatus.OK with a success message to clients.

packages/core/src/lib/employee-notification/employee-notification.service.ts (3)

37-86: Add unit tests for the create method.
This create method contains important business logic—such as handling default notification settings, verifying notification allowances, and persisting the entity—which should be thoroughly tested to prevent regressions and ensure correctness.

Would you like help generating a set of unit tests to validate the different branches of this logic?


76-78: Clarify the return of undefined.
When notifications are disallowed, returning undefined may cause confusion for consumers expecting a valid notification object. Ensure that calling code accounts for this possibility or consider throwing an exception for clearer handling.


83-83: Use NestJS logger instead of console.log.
For consistency with NestJS logging best practices, replace console.log statements with Nest's built-in logger (e.g., Logger.log).

- console.log('Error while creating notification:', error);
+ Logger.error('Error while creating notification:', error);
packages/core/src/lib/employee-notification/employee-notification-setting/commands/employee-notification-setting.create.command.ts (1)

4-8: LGTM! Consider adding class documentation.

The command implementation follows CQRS pattern best practices with proper typing and immutability.

Consider adding JSDoc documentation to describe the command's purpose and input structure:

+/**
+ * Command to create a new employee notification setting
+ * @class EmployeeNotificationSettingCreateCommand
+ */
 export class EmployeeNotificationSettingCreateCommand implements ICommand {
packages/core/src/lib/employee-notification/employee-notification-setting/commands/employee-notification-setting.update.command.ts (1)

4-8: LGTM! Consider adding class documentation.

The command implementation follows CQRS pattern best practices with proper typing and immutability.

Consider adding JSDoc documentation to describe the command's purpose and parameters:

+/**
+ * Command to update an existing employee notification setting
+ * @class EmployeeNotificationSettingUpdateCommand
+ * @param id - The ID of the notification setting to update
+ * @param input - The update data
+ */
 export class EmployeeNotificationSettingUpdateCommand implements ICommand {
packages/core/src/lib/employee-notification/repository/type-orm-employee-notification.repository.ts (1)

6-11: LGTM! Consider adding error handling and documentation.

The repository implementation follows TypeORM and NestJS patterns correctly.

Consider these improvements:

  1. Add error handling for repository initialization:
 constructor(@InjectRepository(EmployeeNotification) readonly repository: Repository<EmployeeNotification>) {
+    if (!repository) {
+        throw new Error('EmployeeNotification repository not provided');
+    }
     super(repository.target, repository.manager, repository.queryRunner);
 }
  1. Add class documentation:
+/**
+ * TypeORM repository for managing employee notifications
+ * @class TypeOrmEmployeeNotificationRepository
+ */
 @Injectable()
 export class TypeOrmEmployeeNotificationRepository extends Repository<EmployeeNotification> {
packages/core/src/lib/employee-notification/employee-notification-setting/repository/type-orm-employee-notification-setting.repository.ts (1)

7-13: Consider adding custom repository methods for common queries.

While extending the TypeORM Repository provides basic CRUD operations, consider adding custom methods for frequently used queries to improve code reusability and maintainability.

Example methods to consider:

async findByEmployeeId(employeeId: string): Promise<EmployeeNotificationSetting> {
  return this.findOne({ where: { employeeId } });
}

async findByTenantAndOrganization(tenantId: string, organizationId: string): Promise<EmployeeNotificationSetting[]> {
  return this.find({ where: { tenantId, organizationId } });
}
packages/contracts/src/lib/employee-notification-setting.model.ts (1)

4-15: Enhance JSDoc documentation and type definitions.

While the interface is well-structured, the documentation and type definitions could be improved.

Consider these improvements:

/**
 * Interface for employee notification settings.
 * Defines the structure for managing notification preferences per employee.
 * 
 * @property payment - Whether to receive payment-related notifications
 * @property assignment - Whether to receive task assignment notifications
 * @property invitation - Whether to receive invitation notifications
 * @property mention - Whether to receive mention notifications
 * @property comment - Whether to receive comment notifications
 * @property message - Whether to receive message notifications
 * @property preferences - Additional notification preferences in JSON format
 */
export interface IEmployeeNotificationSetting extends IEmployeeEntityInput, IBasePerTenantAndOrganizationEntityModel {
  payment?: boolean;
  assignment?: boolean;
  invitation?: boolean;
  mention?: boolean;
  comment?: boolean;
  message?: boolean;
  preferences?: Record<string, unknown>;  // More specific than JsonData
}
packages/core/src/lib/employee-notification/employee-notification.module.ts (1)

16-17: Consider standardizing ORM usage.

The module is configured to use both TypeORM and MikroORM simultaneously. This dual ORM setup could lead to:

  • Increased maintenance overhead
  • Potential data consistency issues
  • Added complexity in repository implementations

Consider standardizing on a single ORM across the application to reduce complexity and maintenance overhead.

packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.module.ts (1)

20-20: Consider explicit command handler registration.

Using spread operator with CommandHandlers could make it harder to track which handlers are actually registered.

Consider listing command handlers explicitly for better code clarity:

-	providers: [EmployeeNotificationSettingService, TypeOrmEmployeeNotificationSettingRepository, ...CommandHandlers],
+	providers: [
+		EmployeeNotificationSettingService,
+		TypeOrmEmployeeNotificationSettingRepository,
+		EmployeeNotificationSettingCreateHandler,
+		EmployeeNotificationSettingUpdateHandler
+	],
packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.service.ts (2)

24-36: Enhance error handling with specific error types.

The current error handling catches all errors and converts them to HttpException. Consider handling specific error types differently.

 async create(input: IEmployeeNotificationSettingCreateInput): Promise<EmployeeNotificationSetting> {
   try {
     const tenantId = RequestContext.currentTenantId() || input.tenantId;
     const employeeId = input.employeeId || RequestContext.currentEmployeeId();

     return super.create({ ...input, employeeId, tenantId });
   } catch (error) {
-    throw new HttpException(
-      `Failed to create the notification setting: ${error.message}`,
-      HttpStatus.BAD_REQUEST
-    );
+    if (error instanceof TypeError) {
+      throw new HttpException(
+        'Invalid input data for notification setting',
+        HttpStatus.BAD_REQUEST
+      );
+    }
+    if (error.code === '23505') { // PostgreSQL unique violation
+      throw new HttpException(
+        'Notification setting already exists',
+        HttpStatus.CONFLICT
+      );
+    }
+    throw new HttpException(
+      'Failed to create notification setting',
+      HttpStatus.INTERNAL_SERVER_ERROR
+    );
   }
 }

18-23: Improve method documentation.

The JSDoc comment could be more descriptive about the parameters and potential errors.

 /**
  * Creates an employee notification setting record
  *
- * @param {IEmployeeNotificationSetting} input - The input data for creating a notification setting
+ * @param {IEmployeeNotificationSettingCreateInput} input - The input data containing notification preferences
+ * @param {string} [input.tenantId] - Optional tenant ID. If not provided, current tenant ID is used
+ * @param {string} [input.employeeId] - Optional employee ID. If not provided, current employee ID is used
  * @returns {Promise<EmployeeNotificationSetting>} The created notification setting
+ * @throws {HttpException} When creation fails or input is invalid
  */
packages/core/src/lib/employee-notification/employee-notification-type-transform.ts (1)

15-32: Refactor enum mapping to reduce maintenance overhead.

The current implementation uses magic numbers and requires maintaining two switch statements. Consider using a mapping object.

+private static readonly enumToNumber = {
+  [EmployeeNotificationTypeEnum.PAYMENT]: 0,
+  [EmployeeNotificationTypeEnum.ASSIGNMENT]: 1,
+  [EmployeeNotificationTypeEnum.INVITATION]: 2,
+  [EmployeeNotificationTypeEnum.MENTION]: 3,
+  [EmployeeNotificationTypeEnum.COMMENT]: 4,
+  [EmployeeNotificationTypeEnum.MESSAGE]: 5,
+} as const;
+
+private static readonly numberToEnum = Object.fromEntries(
+  Object.entries(EmployeeNotificationTypeTransformer.enumToNumber)
+    .map(([key, value]) => [value, key])
+) as Record<number, EmployeeNotificationTypeEnum>;
+
 to(value: EmployeeNotificationTypeEnum): number {
-  switch (value) {
-    case EmployeeNotificationTypeEnum.PAYMENT:
-      return 0;
-    // ... other cases
-    default:
-      throw new Error(`Unknown notification type: ${value}`);
+  const result = EmployeeNotificationTypeTransformer.enumToNumber[value];
+  if (result === undefined) {
+    throw new Error(`Unknown notification type: ${value}`);
   }
+  return result;
 }
packages/core/src/lib/employee-notification/employee-notification.controller.ts (1)

15-17: Follow naming convention for service injection.

The service property name should be camelCase to follow TypeScript naming conventions.

-constructor(readonly EmployeeNotificationService: EmployeeNotificationService) {
+constructor(readonly employeeNotificationService: EmployeeNotificationService) {
   super(EmployeeNotificationService);
 }
packages/core/src/lib/employee-notification/employee-notification.helper.ts (1)

31-55: Consider adding template validation.

While the implementation is solid, consider adding validation to ensure all required placeholders in a template are provided in the parameters.

 export function generateNotificationTitle(
 	action: NotificationActionTypeEnum,
 	entity: BaseEntityEnum,
 	entityName: string,
 	employeeName: string
 ): string {
 	// Retrieve the template corresponding to the notification action
 	const template = EmployeeNotificationTemplates[action];
+
+	// Extract placeholders from template
+	const requiredPlaceholders = template.match(/\{(\w+)\}/g)?.map(p => p.slice(1, -1)) || [];
+
+	// Validate all required placeholders have corresponding values
+	const missingPlaceholders = requiredPlaceholders.filter(placeholder => {
+		switch (placeholder) {
+			case 'action': return !action;
+			case 'entity': return !entity;
+			case 'entityName': return !entityName;
+			case 'employeeName': return !employeeName;
+			default: return true;
+		}
+	});
+
+	if (missingPlaceholders.length > 0) {
+		throw new Error(`Missing values for placeholders: ${missingPlaceholders.join(', ')}`);
+	}

 	// Replace placeholders in the template with actual values
 	return template.replace(/\{(\w+)\}/g, (_, key) => {
packages/core/src/lib/mention/mention.service.ts (1)

67-82: Consider adding error handling for notification publishing.

The notification publishing should be wrapped in a try-catch block to prevent notification failures from affecting the main mention creation flow.

 			// Trigger internal system notification for mentioned user
+			try {
 			this._employeeNotificationService.publishNotificationEvent(
 				{
 					entity: parentEntityType ?? entity,
 					entityId: parentEntityId ?? entityId,
 					type: EmployeeNotificationTypeEnum.MENTION,
 					sentById: user.id,
 					receiverId: mentionedUserId,
 					organizationId,
 					tenantId
 				},
 				NotificationActionTypeEnum.Mentioned,
 				entityName,
 				`${user.firstName} ${user.lastName}`
 			);
+			} catch (notificationError) {
+				console.warn('Failed to publish notification:', notificationError);
+				// Continue execution as notification failure shouldn't block mention creation
+			}
packages/core/src/lib/tasks/commands/handlers/task-create.handler.ts (2)

33-42: Fix the service name casing.

The service name should follow camelCase convention.

-		private readonly EmployeeNotificationService: EmployeeNotificationService
+		private readonly employeeNotificationService: EmployeeNotificationService

140-169: Consider adding error handling for individual notification failures.

The notification publishing should handle errors individually to prevent a single notification failure from affecting other notifications.

 					// Publish subscription events for each employee and send internal notification to users
 					await Promise.all(
 						employees.map(({ userId }: IEmployee) => {
-							this._cqrsEventBus.publish(
-								new CreateSubscriptionEvent({
-									entity: BaseEntityEnum.Task,
-									entityId: task.id,
-									userId,
-									type: SubscriptionTypeEnum.ASSIGNMENT,
-									organizationId,
-									tenantId
-								})
-							);
+							return Promise.all([
+								this._cqrsEventBus.publish(
+									new CreateSubscriptionEvent({
+										entity: BaseEntityEnum.Task,
+										entityId: task.id,
+										userId,
+										type: SubscriptionTypeEnum.ASSIGNMENT,
+										organizationId,
+										tenantId
+									})
+								).catch(error => {
+									this.logger.error(`Failed to publish subscription for user ${userId}:`, error);
+								}),
 
-							this.EmployeeNotificationService.publishNotificationEvent(
-								{
-									entity: BaseEntityEnum.Task,
-									entityId: task.id,
-									type: EmployeeNotificationTypeEnum.ASSIGNMENT,
-									sentById: task.creatorId,
-									receiverId: userId,
-									organizationId,
-									tenantId
-								},
-								NotificationActionTypeEnum.Assigned,
-								task.title,
-								`${user.firstName} ${user.lastName}`
-							);
+								this.employeeNotificationService.publishNotificationEvent(
+									{
+										entity: BaseEntityEnum.Task,
+										entityId: task.id,
+										type: EmployeeNotificationTypeEnum.ASSIGNMENT,
+										sentById: task.creatorId,
+										receiverId: userId,
+										organizationId,
+										tenantId
+									},
+									NotificationActionTypeEnum.Assigned,
+									task.title,
+									`${user.firstName} ${user.lastName}`
+								).catch(error => {
+									this.logger.error(`Failed to publish notification for user ${userId}:`, error);
+								})
+							]);
 						})
 					);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e8774e1 and afa7223.

📒 Files selected for processing (46)
  • nx.json (1 hunks)
  • packages/contracts/src/index.ts (2 hunks)
  • packages/contracts/src/lib/base-entity.model.ts (2 hunks)
  • packages/contracts/src/lib/employee-notification-setting.model.ts (1 hunks)
  • packages/contracts/src/lib/employee-notification.model.ts (1 hunks)
  • packages/core/src/lib/activity-log/activity-log.entity.ts (2 hunks)
  • packages/core/src/lib/app/app.module.ts (2 hunks)
  • packages/core/src/lib/comment/comment.entity.ts (3 hunks)
  • packages/core/src/lib/core/entities/index.ts (2 hunks)
  • packages/core/src/lib/core/entities/internal.ts (3 hunks)
  • packages/core/src/lib/core/entities/subscribers/index.ts (2 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/commands/employee-notification-setting.create.command.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/commands/employee-notification-setting.update.command.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/commands/handlers/employee-notification-setting.create.handler.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/commands/handlers/employee-notification-setting.update.handler.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/commands/handlers/index.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/commands/index.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/dto/create-employee-notification-setting.dto.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/dto/index.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/dto/update-employee-notification-setting.dto.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.controller.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.entity.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.module.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.service.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.subscriber.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/repository/mikro-orm-employee-notification-setting.repository.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-setting/repository/type-orm-employee-notification-setting.repository.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification-type-transform.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification.controller.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification.entity.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification.helper.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification.module.ts (1 hunks)
  • packages/core/src/lib/employee-notification/employee-notification.service.ts (1 hunks)
  • packages/core/src/lib/employee-notification/events/employee-notification.event.ts (1 hunks)
  • packages/core/src/lib/employee-notification/events/handlers/employee-notification.handler.ts (1 hunks)
  • packages/core/src/lib/employee-notification/events/handlers/index.ts (1 hunks)
  • packages/core/src/lib/employee-notification/events/index.ts (1 hunks)
  • packages/core/src/lib/employee-notification/repository/mikro-orm-employee-notification.repository.ts (1 hunks)
  • packages/core/src/lib/employee-notification/repository/type-orm-employee-notification.repository.ts (1 hunks)
  • packages/core/src/lib/mention/mention.module.ts (2 hunks)
  • packages/core/src/lib/mention/mention.service.ts (3 hunks)
  • packages/core/src/lib/shared/pipes/actor-type-transform.ts (1 hunks)
  • packages/core/src/lib/shared/pipes/index.ts (1 hunks)
  • packages/core/src/lib/tasks/commands/handlers/task-create.handler.ts (7 hunks)
  • packages/core/src/lib/tasks/task.module.ts (2 hunks)
  • packages/core/src/lib/tasks/task.service.ts (6 hunks)
✅ Files skipped from review due to trivial changes (3)
  • packages/core/src/lib/employee-notification/events/index.ts
  • packages/core/src/lib/shared/pipes/index.ts
  • packages/core/src/lib/employee-notification/employee-notification-setting/dto/index.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/core/src/lib/tasks/task.module.ts
  • packages/core/src/lib/mention/mention.module.ts
  • packages/core/src/lib/app/app.module.ts
  • packages/core/src/lib/core/entities/subscribers/index.ts
  • packages/core/src/lib/core/entities/index.ts
  • packages/contracts/src/lib/base-entity.model.ts
  • packages/core/src/lib/core/entities/internal.ts
  • packages/contracts/src/index.ts
🧰 Additional context used
🪛 Gitleaks (8.21.2)
nx.json

88-88: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: build
  • GitHub Check: test
🔇 Additional comments (29)
nx.json (4)

2-18: Approved: "namedInputs" Configuration Looks Good

The "namedInputs" section is well structured and consistent with Nx conventions. All the defined input paths and groupings (default, sharedGlobals, production) appear correctly set up.


19-27: Approved: "cli" Settings are Configured Properly

The CLI configuration disables specific warnings and correctly sets the package manager and analytics options. This aligns with the project’s operational preferences.


28-85: Approved: "generators" Section is Comprehensive

The generators configuration for Angular applications, libraries, and components is detailed and follows established conventions in the repository. All properties (linter, style, test runners, etc.) are well organized.


90-171: Approved: "targetDefaults" Section is Detailed

The "targetDefaults" configuration for various tasks such as build, lint, test, and e2e is comprehensive and appears to follow best practices in caching and dependency handling. No changes required here.

packages/core/src/lib/shared/pipes/actor-type-transform.ts (1)

5-8: LGTM! The class name change better reflects its purpose.

The renaming from ActorTypeTransformerPipe to ActorTypeTransformer is more accurate as this class is a TypeORM value transformer, not a pipe. The documentation has been appropriately updated to reflect this change.

packages/core/src/lib/activity-log/activity-log.entity.ts (3)

7-8: LGTM! Import statements have been cleaned up.

The imports have been appropriately updated to reflect the new base class and removed unused imports.


28-28: LGTM! Transformer reference has been updated.

The transformer reference has been correctly updated to use the renamed ActorTypeTransformer class.


14-14: Verify the impact of changing the base class.

The change from TenantOrganizationBaseEntity to BasePerEntityType might affect tenant/organization relationships. Please ensure that:

  1. All required tenant/organization functionality is preserved
  2. Existing queries and filters still work as expected
  3. Data migration plans are in place
❌ Verification inconclusive

🏁 Script executed:

#!/bin/bash
# Search for references to ActivityLog entity in queries and repositories
rg -A 5 "ActivityLog.*tenant|ActivityLog.*organization" --type ts

Length of output: 67


Manual Verification Required: Impact of Base Class Change on Tenant/Organization Logic

The automated search did not produce any direct references linking ActivityLog to tenant or organization filtering. However, this absence of results doesn’t definitively confirm that all tenant/organization functionality and data migration considerations have been preserved. Please manually verify that:

  • The necessary tenant/organization fields and relationships in ActivityLog are maintained after switching from TenantOrganizationBaseEntity to BasePerEntityType.
  • All existing queries and filters that might implicitly rely on the previous base class still operate as expected.
  • There is an appropriate data migration strategy in place for transitioning any tenant/organization-specific data.
packages/core/src/lib/comment/comment.entity.ts (4)

7-8: LGTM! Clean import organization.

The import statements are well-organized and correctly aligned with the class changes.

Also applies to: 17-17


63-179: LGTM! Well-structured entity with proper relationships.

The entity maintains clean and well-documented relationships with appropriate cascade rules and comprehensive validation decorators.


34-34: Verify the transformer functionality.

The change from ActorTypeTransformerPipe to ActorTypeTransformer appears to be a refactoring. Let's verify that the new transformer maintains the same functionality for the actorType field.

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Description: Check the implementation of both transformers
# to ensure functionality remains the same

echo "Checking ActorTypeTransformer implementation..."
ast-grep --pattern 'class ActorTypeTransformer {
  $$$
}'

echo "Checking for any remaining references to ActorTypeTransformerPipe..."
rg "ActorTypeTransformerPipe" -l

Length of output: 344


Transformer functionality verified.

  • The new ActorTypeTransformer class is present in the codebase.
  • No occurrences of the old ActorTypeTransformerPipe were detected.

Based on the inspection, the refactoring appears to have been applied correctly, preserving the expected transformer functionality for the actorType field.


21-21: Verify the inheritance change impact across the codebase.

The change from TenantOrganizationBaseEntity to BasePerEntityType is a significant architectural modification. Let's verify that this change is consistently applied across related entities and doesn't break existing functionality.

✅ Verification successful

🏁 Script executed:

#!/bin/bash
# Description: Check for any remaining references to TenantOrganizationBaseEntity
# and verify consistent usage of BasePerEntityType in related files

echo "Checking for remaining TenantOrganizationBaseEntity references..."
rg "TenantOrganizationBaseEntity" -l

echo "Checking BasePerEntityType usage in related entities..."
rg "extends BasePerEntityType" -l

echo "Checking for potential migration files related to this change..."
fd -e ts -p ".*migration.*" -x rg -l "comment.*table|BasePerEntityType"

Length of output: 10960


Inheritance Change Impact Verified

  • The Comment entity now extends BasePerEntityType—just like several related entities (e.g., the ones in activity-log, favorite, mention, resource-link, subscription, and employee-notification).
  • A search shows that many entities still extend TenantOrganizationBaseEntity; however, this appears to be an intentional, incremental migration rather than an oversight.
  • No migration files specific to this change in the comment module were found, suggesting no unexpected side effects for this particular update.

Overall, the inheritance change in comment.entity.ts is applied consistently within its intended context. Please ensure that the selective migration strategy (updating only some entities) is documented and that the entities retaining TenantOrganizationBaseEntity are meant to behave differently.

packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.subscriber.ts (1)

6-7: Good use of TypeORM event subscriber.

The declaration correctly identifies that this subscriber will listen to events for the EmployeeNotificationSetting entity. This is aligned with the recommended approach for TypeORM event subscribers and helps keep domain logic clean.

packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.controller.ts (2)

54-58: Ensure pagination correctness and edge case handling.

Within the findAll method, consider validating whether pagination parameters (like page size or page number) are within acceptable ranges. This helps protect system performance and user experience.


95-99: Validate default boolean flags in the DTO.

When creating a new notification setting, ensure your DTO or command handler either merges default boolean flags (e.g., true for payment, assignment) or references them from the server-side defaults. This can protect against partial data or injection attacks.

packages/core/src/lib/employee-notification/employee-notification-setting/employee-notification-setting.entity.ts (1)

112-128: Double check “cascade” implications for employee relation.

With cascade: true and onDelete: 'CASCADE', deleting an employee will remove all notification settings automatically. Verify it’s intentional. If not, you might want to handle cascade options more selectively to prevent accidental data loss.

packages/core/src/lib/employee-notification/employee-notification.service.ts (1)

138-158: Verify default notification settings.
The shouldCreateEmployeeNotification method defaults all unset notification preferences to true. Confirm this is the intended design, as users with unconfigured settings might receive more notifications than desired.

packages/core/src/lib/employee-notification/employee-notification-setting/commands/index.ts (1)

1-2: LGTM.
Re-exporting commands via the index file simplifies imports across the codebase.

packages/core/src/lib/employee-notification/events/handlers/index.ts (1)

1-3: LGTM.
Exporting EventHandlers as an array of handlers is a standard NestJS convention, making it straightforward to provide these handlers to any module.

packages/core/src/lib/employee-notification/events/employee-notification.event.ts (1)

1-6: LGTM! Clean implementation following CQRS pattern.

The event class is well-structured with proper immutability using readonly modifier and follows the CQRS pattern for event handling.

packages/core/src/lib/employee-notification/repository/mikro-orm-employee-notification.repository.ts (1)

1-4: LGTM! Clean repository implementation.

The repository follows best practices by extending the base repository and properly typing it for EmployeeNotification entities.

packages/core/src/lib/employee-notification/employee-notification-setting/repository/mikro-orm-employee-notification-setting.repository.ts (1)

1-4: LGTM! Clean repository implementation.

The repository follows best practices by extending the base repository and properly typing it for EmployeeNotificationSetting entities.

packages/core/src/lib/employee-notification/employee-notification-setting/commands/handlers/index.ts (1)

1-4: LGTM! Clean barrel export implementation.

The file follows best practices by using the barrel pattern to export multiple command handlers, making it easier to import them elsewhere.

packages/core/src/lib/employee-notification/employee-notification-setting/dto/update-employee-notification-setting.dto.ts (1)

5-10: LGTM! Well-documented DTO implementation.

The DTO implementation follows best practices by:

  • Using PartialType to make all properties optional for updates
  • Implementing the contract interface for type safety
  • Including clear documentation
packages/core/src/lib/employee-notification/employee-notification.helper.ts (1)

3-10: LGTM! Well-structured notification templates.

The templates are clearly defined and cover various notification types with consistent placeholder usage.

packages/core/src/lib/employee-notification/employee-notification.entity.ts (1)

12-132: LGTM! Well-designed entity with proper validation and indexing.

The entity is well-structured with:

  • Proper validation using class-validator
  • Indexed columns for performance
  • Correct cascade delete behavior for relations
  • Clear documentation
packages/core/src/lib/mention/mention.service.ts (1)

24-31: LGTM! Proper dependency injection.

The service correctly injects the required dependencies.

packages/core/src/lib/tasks/task.service.ts (2)

31-33: LGTM! Clean dependency injection for notification service.

The imports and constructor injection for the employee notification service are properly implemented.

Also applies to: 44-44, 64-64


81-81: Consider handling subscription and notification events atomically.

While the notification implementation is correct, publishing the subscription and notification events separately could lead to a race condition where a user might receive a notification before being subscribed to the task.

Consider wrapping both events in a transaction or using an event aggregator:

-this._eventBus.publish(
-    new CreateSubscriptionEvent({
-        entity: BaseEntityEnum.Task,
-        entityId: updatedTask.id,
-        userId,
-        type: SubscriptionTypeEnum.ASSIGNMENT,
-        organizationId,
-        tenantId
-    })
-);
-
-this.employeeNotificationService.publishNotificationEvent(
-    {
-        entity: BaseEntityEnum.Task,
-        entityId: task.id,
-        type: EmployeeNotificationTypeEnum.ASSIGNMENT,
-        sentById: user.id,
-        receiverId: userId,
-        organizationId,
-        tenantId
-    },
-    NotificationActionTypeEnum.Assigned,
-    task.title,
-    `${user.firstName} ${user.lastName}`
-);
+// Create an aggregated event that handles both subscription and notification
+await this.handleTaskAssignment({
+    task: updatedTask,
+    userId,
+    user,
+    organizationId,
+    tenantId
+});

Also applies to: 193-206

Comment on lines +86 to +90
"defaultProject": "gauzy",
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"nxCloudAccessToken": "NWJlMDFmMTMtYzUyZS00ZGE4LTk0NzctNWIzZTkxMzNhMTFlfHJlYWQtd3JpdGU=",
"parallel": 1,
"targetDefaults": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical Issue: Hardcoded nxCloudAccessToken Detected

Line 88 reveals a hardcoded API key in the "nxCloudAccessToken" field. Embedding sensitive tokens in source-controlled configuration files risks exposure and potential misuse. It is recommended to remove the static token and replace it with a dynamic reference to an environment variable, for example:

-    "nxCloudAccessToken": "NWJlMDFmMTMtYzUyZS00ZGE4LTk0NzctNWIzZTkxMzNhMTFlfHJlYWQtd3JpdGU=",
+    "nxCloudAccessToken": "${NX_CLOUD_ACCESS_TOKEN}",

This change helps ensure sensitive data is managed securely.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"defaultProject": "gauzy",
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"nxCloudAccessToken": "NWJlMDFmMTMtYzUyZS00ZGE4LTk0NzctNWIzZTkxMzNhMTFlfHJlYWQtd3JpdGU=",
"parallel": 1,
"targetDefaults": {
"defaultProject": "gauzy",
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"nxCloudAccessToken": "${NX_CLOUD_ACCESS_TOKEN}",
"parallel": 1,
"targetDefaults": {
🧰 Tools
🪛 Gitleaks (8.21.2)

88-88: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

Comment on lines +90 to +106
/**
* Stores additional, custom notification preferences in a JSON format.
*
* This field allows for flexible storage of any extra preferences not covered by the
* standard boolean properties above. The underlying database column type adapts based on the
* database in use:
* - PostgreSQL: Uses 'jsonb'
* - MySQL: Uses 'json'
* - Other databases: Defaults to 'text'
*
* This field is required and must not be empty.
*/
@ApiProperty({ type: () => Object })
@IsNotEmpty()
@MultiORMColumn({ type: isPostgres() ? 'jsonb' : isMySQL() ? 'json' : 'text' })
preferences?: JsonData;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Reconcile the “required” property with its optional type.

The docstring indicates "preferences is required," but the property is typed as preferences?: JsonData;. Additionally, @IsNotEmpty() changes the validation semantics. Consider making preferences mandatory in the type definition or adjusting the docs/validation to reflect optional usage.

- @IsNotEmpty()
- preferences?: JsonData;
+ @IsNotEmpty()
+ preferences: JsonData;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Stores additional, custom notification preferences in a JSON format.
*
* This field allows for flexible storage of any extra preferences not covered by the
* standard boolean properties above. The underlying database column type adapts based on the
* database in use:
* - PostgreSQL: Uses 'jsonb'
* - MySQL: Uses 'json'
* - Other databases: Defaults to 'text'
*
* This field is required and must not be empty.
*/
@ApiProperty({ type: () => Object })
@IsNotEmpty()
@MultiORMColumn({ type: isPostgres() ? 'jsonb' : isMySQL() ? 'json' : 'text' })
preferences?: JsonData;
/**
* Stores additional, custom notification preferences in a JSON format.
*
* This field allows for flexible storage of any extra preferences not covered by the
* standard boolean properties above. The underlying database column type adapts based on the
* database in use:
* - PostgreSQL: Uses 'jsonb'
* - MySQL: Uses 'json'
* - Other databases: Defaults to 'text'
*
* This field is required and must not be empty.
*/
@ApiProperty({ type: () => Object })
@IsNotEmpty()
@MultiORMColumn({ type: isPostgres() ? 'jsonb' : isMySQL() ? 'json' : 'text' })
preferences: JsonData;

Comment on lines +9 to +14
export class CreateEmployeeNotificationSettingDTO
extends IntersectionType(
TenantOrganizationBaseDTO,
OmitType(EmployeeNotificationSetting, ['employee', 'employeeId'])
)
implements IEmployeeNotificationSettingCreateInput {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add validation decorators for request validation.

The DTO lacks validation decorators which are essential for ensuring data integrity and providing clear API validation errors.

Consider adding class-validator decorators:

export class CreateEmployeeNotificationSettingDTO
  extends IntersectionType(
    TenantOrganizationBaseDTO,
    OmitType(EmployeeNotificationSetting, ['employee', 'employeeId'])
  )
  implements IEmployeeNotificationSettingCreateInput {
    
    @IsOptional()
    @IsBoolean()
    payment?: boolean;

    @IsOptional()
    @IsBoolean()
    assignment?: boolean;

    @IsOptional()
    @IsBoolean()
    invitation?: boolean;

    @IsOptional()
    @IsBoolean()
    mention?: boolean;

    @IsOptional()
    @IsBoolean()
    comment?: boolean;

    @IsOptional()
    @IsBoolean()
    message?: boolean;

    @IsOptional()
    @IsObject()
    preferences?: JsonData;
}

Comment on lines +16 to +18
async handle(event: EmployeeCreateNotificationEvent) {
return await this.employeeNotificationService.create(event.input);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling and logging.

The handle method should include proper error handling and logging for better observability and debugging.

Consider this implementation:

@Injectable()
export class EmployeeCreateNotificationEventHandler implements IEventHandler<EmployeeCreateNotificationEvent> {
  private readonly logger = new Logger(EmployeeCreateNotificationEventHandler.name);

  constructor(
    private readonly employeeNotificationService: EmployeeNotificationService
  ) {}

  async handle(event: EmployeeCreateNotificationEvent) {
    try {
      this.logger.debug(`Creating notification for employee: ${event.input.employeeId}`);
      const notification = await this.employeeNotificationService.create(event.input);
      this.logger.debug(`Successfully created notification: ${notification.id}`);
      return notification;
    } catch (error) {
      this.logger.error(`Failed to create notification: ${error.message}`, error.stack);
      throw new Error(`Failed to create employee notification: ${error.message}`);
    }
  }
}

Comment on lines +18 to +21
public async execute(command: EmployeeNotificationSettingCreateCommand): Promise<IEmployeeNotificationSetting> {
const { input } = command;
return this.employeeNotificationSettingService.create(input);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling and input validation.

The execute method should handle potential errors from the service layer and validate input data.

Consider adding error handling and validation:

 public async execute(command: EmployeeNotificationSettingCreateCommand): Promise<IEmployeeNotificationSetting> {
 		const { input } = command;
+		if (!input) {
+			throw new Error('Input is required for creating notification setting');
+		}
+		try {
 			return this.employeeNotificationSettingService.create(input);
+		} catch (error) {
+			// Log error details
+			throw new Error(`Failed to create notification setting: ${error.message}`);
+		}
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public async execute(command: EmployeeNotificationSettingCreateCommand): Promise<IEmployeeNotificationSetting> {
const { input } = command;
return this.employeeNotificationSettingService.create(input);
}
public async execute(command: EmployeeNotificationSettingCreateCommand): Promise<IEmployeeNotificationSetting> {
const { input } = command;
if (!input) {
throw new Error('Input is required for creating notification setting');
}
try {
return this.employeeNotificationSettingService.create(input);
} catch (error) {
// Log error details
throw new Error(`Failed to create notification setting: ${error.message}`);
}
}

Comment on lines +19 to +24
public async execute(
command: EmployeeNotificationSettingUpdateCommand
): Promise<IEmployeeNotificationSetting | UpdateResult> {
const { id, input } = command;
return this.employeeNotificationSettingService.update(id, input);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Standardize return type and add error handling.

The handler returns a union type which could complicate error handling for consumers. Also, error handling is missing.

Consider standardizing the return type and adding error handling:

 	public async execute(
 		command: EmployeeNotificationSettingUpdateCommand
-	): Promise<IEmployeeNotificationSetting | UpdateResult> {
+	): Promise<IEmployeeNotificationSetting> {
 		const { id, input } = command;
+		if (!id || !input) {
+			throw new Error('Both id and input are required for updating notification setting');
+		}
+		try {
-			return this.employeeNotificationSettingService.update(id, input);
+			const result = await this.employeeNotificationSettingService.update(id, input);
+			if (result instanceof UpdateResult) {
+				// Fetch and return the updated entity
+				return this.employeeNotificationSettingService.findOne(id);
+			}
+			return result;
+		} catch (error) {
+			// Log error details
+			throw new Error(`Failed to update notification setting: ${error.message}`);
+		}
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public async execute(
command: EmployeeNotificationSettingUpdateCommand
): Promise<IEmployeeNotificationSetting | UpdateResult> {
const { id, input } = command;
return this.employeeNotificationSettingService.update(id, input);
}
public async execute(
command: EmployeeNotificationSettingUpdateCommand
): Promise<IEmployeeNotificationSetting> {
const { id, input } = command;
if (!id || !input) {
throw new Error('Both id and input are required for updating notification setting');
}
try {
const result = await this.employeeNotificationSettingService.update(id, input);
if (result instanceof UpdateResult) {
// Fetch and return the updated entity
return this.employeeNotificationSettingService.findOne(id);
}
return result;
} catch (error) {
// Log error details
throw new Error(`Failed to update notification setting: ${error.message}`);
}
}

Comment on lines +8 to +19
export interface IEmployeeNotification extends IBasePerEntityType {
title?: string;
message?: string;
type?: EmployeeNotificationTypeEnum;
sentById?: ID;
sentBy?: IEmployee;
isRead?: boolean;
readAt?: Date;
onHoldUntil?: Date;
receiverId?: ID;
receiver?: IEmployee;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Make essential properties required.

Some properties should be non-optional for proper functionality of the notification system.

 export interface IEmployeeNotification extends IBasePerEntityType {
-  title?: string;
-  message?: string;
-  type?: EmployeeNotificationTypeEnum;
-  sentById?: ID;
-  sentBy?: IEmployee;
-  isRead?: boolean;
+  title: string;
+  message: string;
+  type: EmployeeNotificationTypeEnum;
+  sentById: ID;
+  sentBy?: IEmployee; // Keep optional as it may be populated later
+  isRead: boolean;
   readAt?: Date;
   onHoldUntil?: Date;
-  receiverId?: ID;
+  receiverId: ID;
   receiver?: IEmployee;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface IEmployeeNotification extends IBasePerEntityType {
title?: string;
message?: string;
type?: EmployeeNotificationTypeEnum;
sentById?: ID;
sentBy?: IEmployee;
isRead?: boolean;
readAt?: Date;
onHoldUntil?: Date;
receiverId?: ID;
receiver?: IEmployee;
}
export interface IEmployeeNotification extends IBasePerEntityType {
title: string;
message: string;
type: EmployeeNotificationTypeEnum;
sentById: ID;
sentBy?: IEmployee; // Keep optional as it may be populated later
isRead: boolean;
readAt?: Date;
onHoldUntil?: Date;
receiverId: ID;
receiver?: IEmployee;
}

Comment on lines +53 to +62
@ApiOperation({ summary: 'Mark all notifications as read' })
@ApiResponse({
status: HttpStatus.CREATED,
description: 'The records have been successfully updated.'
})
@HttpCode(HttpStatus.ACCEPTED)
@Put('/mark-all-read')
async markAllAsRead(): Promise<any> {
return await this.EmployeeNotificationService.markAllAsRead();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix inconsistent HTTP status and improve return type.

The endpoint documentation and actual status code are inconsistent. Also, the return type should be more specific.

 @ApiOperation({ summary: 'Mark all notifications as read' })
 @ApiResponse({
-  status: HttpStatus.CREATED,
+  status: HttpStatus.ACCEPTED,
   description: 'The records have been successfully updated.'
 })
 @HttpCode(HttpStatus.ACCEPTED)
 @Put('/mark-all-read')
-async markAllAsRead(): Promise<any> {
+async markAllAsRead(): Promise<{ success: boolean; count: number }> {
   return await this.EmployeeNotificationService.markAllAsRead();
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@ApiOperation({ summary: 'Mark all notifications as read' })
@ApiResponse({
status: HttpStatus.CREATED,
description: 'The records have been successfully updated.'
})
@HttpCode(HttpStatus.ACCEPTED)
@Put('/mark-all-read')
async markAllAsRead(): Promise<any> {
return await this.EmployeeNotificationService.markAllAsRead();
}
@ApiOperation({ summary: 'Mark all notifications as read' })
@ApiResponse({
status: HttpStatus.ACCEPTED,
description: 'The records have been successfully updated.'
})
@HttpCode(HttpStatus.ACCEPTED)
@Put('/mark-all-read')
async markAllAsRead(): Promise<{ success: boolean; count: number }> {
return await this.EmployeeNotificationService.markAllAsRead();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants