Skip to content

Add endpoint for linking skills to task #186

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

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

Conversation

sunilk429
Copy link

@sunilk429 sunilk429 commented Mar 21, 2025

Date: 21st March 2025

Developer Name: @sunilk429


Issue Ticket Number

#172

Description

This PR implements the functionality for linking skills to the task.
For further details here is the design doc

Documentation Updated?

  • Yes
  • No

Under Feature Flag

  • Yes
  • No

Database Changes

  • Yes
  • No

Breaking Changes

  • Yes
  • No

Development Tested?

  • Yes
  • No

Screenshots

Screenshot 1

Test Coverage

Screenshot 1

Additional Notes

Copy link

coderabbitai bot commented Mar 21, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Summary by CodeRabbit

  • New Features
    • Enabled authorized users to easily link skills with tasks for enhanced task management.
    • Added user-friendly validations and feedback to prevent duplicate or invalid associations.
  • Chores
    • Upgraded the database structure to efficiently support and maintain task-skill linking functionality.

Walkthrough

The changes introduce a new REST controller to handle task-skill associations via a POST endpoint, incorporating role-based access control and input validation. New exception handling is added to manage duplicate associations through a custom exception. Additional domain models, including a JPA entity with an embedded composite key, support persistence. Moreover, repository, service (with transactional support), and view model layers have been implemented to facilitate the creation process. A corresponding SQL migration script is provided to create the necessary database table with appropriate constraints.

Changes

Files Change Summary
skill-tree/.../apis/TaskSkillApi.java Added a new REST controller with a POST endpoint to create task-skill associations, including role-based access and request validation.
skill-tree/.../exceptions/GlobalExceptionHandler.java, skill-tree/.../exceptions/TaskSkillAssociationAlreadyExistsException.java Added a custom exception class and an exception handler method to manage duplicate task-skill associations with a 409 response.
skill-tree/.../models/TaskSkill.java, skill-tree/.../models/TaskSkillId.java Introduced a new JPA entity and an embeddable composite key for persisting task-skill associations with audit fields.
skill-tree/.../repositories/TaskSkillRepository.java Added a repository interface with a custom finder method to retrieve associations by taskId.
skill-tree/.../services/TaskSkillService.java, skill-tree/.../services/TaskSkillServiceImplementation.java Implemented a service layer for creating task-skill associations with duplicate checks, validation, and transactional handling.
skill-tree/.../viewmodels/CreateTaskSkillViewModel.java, skill-tree/.../viewmodels/TaskSkillRequestViewModel.java Added view models for request payload and response messages in the task-skill creation process.
skill-tree/.../db/migrations/V2__task_skills_association_table.sql Added a migration script to create the task_skills table with a composite primary key, timestamps, and foreign key constraints.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant API as TaskSkillApi
    participant S as TaskSkillService
    participant SR as SkillRepository
    participant TR as TaskSkillRepository
    U->>API: POST /v1/tasks/{taskId}/skills with request body
    API->>S: createTaskSkills(taskId, skillIds, createdBy)
    loop For each unique skillId
        S->>SR: Retrieve Skill (if not found: throw SkillNotFoundException)
        alt Skill exists
            S->>TR: Check for existing association
            alt Association exists
                S-->>API: Throw TaskSkillAssociationAlreadyExistsException
            else
                S->>TR: Save new TaskSkill association
            end
        else
            S-->>API: Throw SkillNotFoundException
        end
    end
    S-->>API: Return CreateTaskSkillViewModel
    API-->>U: HTTP 200 OK with response
Loading

Poem

Hoppin’ through the lines of code so bright,
I found new paths where skills and tasks unite.
With each association, my world grows neat,
Exceptions and validations dance in beat.
This rabbit cheers—code blooms with delight! 🐰✨


🪧 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.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @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

@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: 9

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 907bf83 and 7b56aba.

📒 Files selected for processing (11)
  • skill-tree/src/main/java/com/RDS/skilltree/apis/TaskSkillApi.java (1 hunks)
  • skill-tree/src/main/java/com/RDS/skilltree/exceptions/GlobalExceptionHandler.java (1 hunks)
  • skill-tree/src/main/java/com/RDS/skilltree/exceptions/TaskSkillAssociationAlreadyExistsException.java (1 hunks)
  • skill-tree/src/main/java/com/RDS/skilltree/models/TaskSkill.java (1 hunks)
  • skill-tree/src/main/java/com/RDS/skilltree/models/TaskSkillId.java (1 hunks)
  • skill-tree/src/main/java/com/RDS/skilltree/repositories/TaskSkillRepository.java (1 hunks)
  • skill-tree/src/main/java/com/RDS/skilltree/services/TaskSkillService.java (1 hunks)
  • skill-tree/src/main/java/com/RDS/skilltree/services/TaskSkillServiceImplementation.java (1 hunks)
  • skill-tree/src/main/java/com/RDS/skilltree/viewmodels/CreateTaskSkillViewModel.java (1 hunks)
  • skill-tree/src/main/java/com/RDS/skilltree/viewmodels/TaskSkillRequestViewModel.java (1 hunks)
  • skill-tree/src/main/resources/db/migrations/V2__task_skills_association_table.sql (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
skill-tree/src/main/java/com/RDS/skilltree/apis/TaskSkillApi.java (1)
skill-tree/src/main/java/com/RDS/skilltree/exceptions/GlobalExceptionHandler.java (1)
  • Slf4j (21-165)
🔇 Additional comments (9)
skill-tree/src/main/java/com/RDS/skilltree/models/TaskSkillId.java (3)

9-16: Well-designed embedded composite key class

The class correctly implements Serializable and uses appropriate Lombok annotations. The @Embeddable annotation properly indicates this class's purpose as a JPA embedded ID.


17-17: Proper serialization versioning

The serialVersionUID is correctly defined to ensure proper serialization/deserialization compatibility.


19-23: Good validation with meaningful error messages

The validation annotations with custom error messages improve the API's usability by providing clear feedback when validation fails.

skill-tree/src/main/resources/db/migrations/V2__task_skills_association_table.sql (1)

1-11:

❓ Verification inconclusive

Consider adding a foreign key constraint for task_id.

The table structure is well-designed with appropriate columns for audit trails and a composite primary key. The foreign key for skill_id properly ensures referential integrity with the skills table.

However, there's no foreign key constraint for task_id. If tasks are stored in a database table within this application, consider adding a foreign key constraint to ensure data integrity.

If tasks are stored in a local table:

CREATE TABLE `task_skills` (
  `task_id` varchar(255) NOT NULL,
  `skill_id` int NOT NULL,
  `created_at` datetime(6) NOT NULL,
  `is_deleted` tinyint(1) NOT NULL DEFAULT '0',
  `updated_at` datetime(6) DEFAULT NULL,
  `created_by` varchar(255) NOT NULL,
  `updated_by` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`task_id`, `skill_id`),
-  CONSTRAINT `fk_task_skills_skill_id` FOREIGN KEY (`skill_id`) REFERENCES `skills` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
+  CONSTRAINT `fk_task_skills_skill_id` FOREIGN KEY (`skill_id`) REFERENCES `skills` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
+  CONSTRAINT `fk_task_skills_task_id` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

🏁 Script executed:

#!/bin/bash
# Check if there's a tasks table in the database schema
echo "Checking if tasks table exists in the database..."

# Look for create table statements for 'tasks'
grep -r "CREATE TABLE.*tasks" --include="*.sql" .

# Look for any migration files related to tasks
find . -name "*.sql" -type f -exec grep -l "tasks" {} \;

# Look for any Task entity in the Java code
find . -name "*.java" -type f -exec grep -l "class Task" {} \;

Length of output: 773


Action Required: Verify the Need for a Foreign Key on task_id

The current schema for the task_skills table is well-designed, and the foreign key on skill_id is correctly enforcing referential integrity with the skills table. However, our check did not reveal any migration file creating a tasks table, nor evidence of a Task entity in the codebase.

Please confirm whether a local tasks table is expected:

  • If a local tasks table exists or is planned, consider adding the following diff to enforce data integrity on task_id:
    CREATE TABLE `task_skills` (
      `task_id` varchar(255) NOT NULL,
      `skill_id` int NOT NULL,
      `created_at` datetime(6) NOT NULL,
      `is_deleted` tinyint(1) NOT NULL DEFAULT '0',
      `updated_at` datetime(6) DEFAULT NULL,
      `created_by` varchar(255) NOT NULL,
      `updated_by` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`task_id`, `skill_id`),
    -  CONSTRAINT `fk_task_skills_skill_id` FOREIGN KEY (`skill_id`) REFERENCES `skills` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
    +  CONSTRAINT `fk_task_skills_skill_id` FOREIGN KEY (`skill_id`) REFERENCES `skills` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
    +  CONSTRAINT `fk_task_skills_task_id` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
  • If the tasks table is managed externally or is not intended to be part of the local database schema, this omission is appropriate.

Please verify that the design decision in your application aligns with one of the above scenarios.

skill-tree/src/main/java/com/RDS/skilltree/exceptions/GlobalExceptionHandler.java (1)

129-135: Exception handler looks good.

The implementation of the handler for TaskSkillAssociationAlreadyExistsException follows the established pattern in the class. It properly logs the error and returns an appropriate HTTP 409 CONFLICT status with a clear error message.

For consistency with other exception handlers in this class that handle similar conflict situations, you've used the correct return type and response structure.

skill-tree/src/main/java/com/RDS/skilltree/services/TaskSkillService.java (1)

1-21:

❓ Verification inconclusive

Well-documented service interface with clear contract.

The TaskSkillService interface is well-defined with a clear method signature and comprehensive Javadoc documentation. The method declaration properly specifies the exceptions that might be thrown.

One suggestion would be to consider adding a method to retrieve task-skill associations, which would complement the creation functionality and provide a complete API for task-skill management.

Consider adding a retrieval method:

public interface TaskSkillService {
    /**
     * Creates associations between a task and multiple skills.
     *
     * @param taskId    The unique identifier of the task.
     * @param skillIds  List of skill identifiers to associate with the task.
     * @param createdBy The identifier of the user creating these associations.
     * @return A response view model indicating success.
     * @throws TaskSkillAssociationAlreadyExistsException if an association already exists.
     * @throws SkillNotFoundException if any skill does not exist.
     */
    CreateTaskSkillViewModel createTaskSkills(
            String taskId, List<Integer> skillIds, String createdBy);
            
+   /**
+    * Retrieves all skills associated with a specific task.
+    *
+    * @param taskId The unique identifier of the task.
+    * @return A list of skills associated with the task.
+    * @throws NoEntityException if the task does not exist.
+    */
+   List<SkillViewModel> getSkillsByTaskId(String taskId);
}

Let's check if there are any classes that would need this retrieval functionality:


🏁 Script executed:

#!/bin/bash
# Check for any files that might benefit from task-skill retrieval functionality
echo "Checking for potential consumers of task-skill retrieval..."

# Look for references to task in the API layer
find . -name "*.java" -path "*/apis/*" -type f -exec grep -l "task" {} \;

# Check for any frontend calls that might need to display skills for a task
find . -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" -type f -exec grep -l "getSkillsByTask" {} \;

Length of output: 392


Enhance Task-Skill Service with a Retrieval Method

The TaskSkillService interface is well documented. Our verification shows that there is at least one consumer in the API layer (skill-tree/src/main/java/com/RDS/skilltree/apis/TaskSkillApi.java) that may benefit from a method to retrieve task-skill associations. While no front-end usage was noted, adding a retrieval method could provide a more comprehensive task-skill management API.

Suggested addition:

 public interface TaskSkillService {
     /**
      * Creates associations between a task and multiple skills.
      *
      * @param taskId    The unique identifier of the task.
      * @param skillIds  List of skill identifiers to associate with the task.
      * @param createdBy The identifier of the user creating these associations.
      * @return A response view model indicating success.
      * @throws TaskSkillAssociationAlreadyExistsException if an association already exists.
      * @throws SkillNotFoundException if any skill does not exist.
      */
     CreateTaskSkillViewModel createTaskSkills(String taskId, List<Integer> skillIds, String createdBy);
     
+    /**
+     * Retrieves all skills associated with a specific task.
+     *
+     * @param taskId The unique identifier of the task.
+     * @return A list of skills associated with the task.
+     * @throws NoEntityException if the task does not exist.
+     */
+    List<SkillViewModel> getSkillsByTaskId(String taskId);
 }

Please review and verify that this enhancement aligns with consumer expectations and overall API design.

skill-tree/src/main/java/com/RDS/skilltree/models/TaskSkill.java (2)

42-46: Potential mismatch between insertable/updateable flags and builder usage.
Since @JoinColumn(name = "skill_id", insertable = false, updatable = false) is paired with an embedded ID, be sure that skill IDs are only ever set via the TaskSkillId. This can be confusing if someone later assumes we can assign a skill directly via .skill(...) in the builder.


11-18:

❓ Verification inconclusive

Consider verifying Spring Data JPA auditing configuration.
The annotations @CreatedDate, @LastModifiedDate, @CreatedBy, and @LastModifiedBy rely on Spring's JPA auditing feature. Please ensure @EnableJpaAuditing is enabled in the application configuration; otherwise, these annotations won't auto-populate.

Use this script to search for @EnableJpaAuditing:


🏁 Script executed:

#!/bin/bash
# Scans for @EnableJpaAuditing annotation usage
rg '@EnableJpaAuditing' -A 3

Length of output: 28


#!/bin/bash
# Re-run a search to verify if Spring Data JPA Auditing is enabled.
# We look for the fully-qualified reference in Java files.
rg 'org.springframework.data.jpa.repository.config.EnableJpaAuditing' --include "*.java"

Verify Spring Data JPA Auditing Configuration

It appears that the initial scan for @EnableJpaAuditing returned no output. To be sure, please re-run the above script or manually verify that a configuration class (typically in your main application or configuration package) is annotated with @EnableJpaAuditing. If no such annotation is found, the auditing annotations (@CreatedDate, @LastModifiedDate, etc.) in TaskSkill.java won’t function as expected.

Please confirm and update the configuration accordingly.

skill-tree/src/main/java/com/RDS/skilltree/apis/TaskSkillApi.java (1)

30-31: Validate regex to ensure alphanumeric consistency.
Because the path variable includes only alphanumeric characters, consider the scenario where additional characters (e.g., underscores, hyphens) might actually appear in task IDs. If the system truly only supports strict [A-Za-z0-9], no action needed. Otherwise, expand the regex.

Copy link
Member

@iamitprakash iamitprakash left a comment

Choose a reason for hiding this comment

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

did you update API contract repo and transferred design doc ownership to RDS

@sunilk429
Copy link
Author

did you update API contract repo and transferred design doc ownership to RDS

I have just transferred ownership to RDS, We don't have skill-tree API contracts in the API contract repo

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.

2 participants