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

Documents rework #3019

Merged
merged 1 commit into from
Feb 4, 2025
Merged

Documents rework #3019

merged 1 commit into from
Feb 4, 2025

Conversation

Omri-Levy
Copy link
Contributor

@Omri-Levy Omri-Levy commented Feb 2, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive document management system that supports creating, retrieving, updating, and deleting documents with associated metadata and files.
    • Enhanced file handling capabilities, including improved upload functionality and routing to appropriate customer folders.
    • Added ENUM types and new tables for better document status and management.
    • Implemented a new service and repository for managing document files, enhancing document-related operations.
    • Added new schemas for validating and transforming document file data.
  • Bug Fixes

    • Improved error handling for file uploads and document retrievals.
  • Refactor

    • Updated the database schema with robust validations and relationships for documents and their files.
    • Simplified business operations by removing redundant document parameters, streamlining interactions across the application.
    • Updated module structures to enhance dependency management and organization.

Copy link

changeset-bot bot commented Feb 2, 2025

⚠️ No Changeset found

Latest commit: b42ddb7

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

coderabbitai bot commented Feb 2, 2025

Walkthrough

The changes update the database schema and application modules to enhance document management capabilities. Updates include modifying the subproject commit reference and several SQL migrations that add new ENUMs, tables (Document, DocumentFile), and columns (such as projectId and issuingCountry). The Prisma schema is updated to include new Document and DocumentFile models and their relationships. Additionally, business and controller endpoints have been simplified by removing the legacy documents field. New modules, services, repositories, and DTOs for documents and document files were introduced, and adjustments were made in file, storage, and workflow modules to support these functionalities.

Changes

File(s) Change Summary
prisma/data-migrations, prisma/migrations/20250129*_migration.sql, prisma/migrations/20250202144546_added_document_file_cascade/migration.sql, prisma/schema.prisma Updated subproject commit; added ENUM types, new tables (Document, DocumentFile), and new columns (projectId, issuingCountry); modified foreign key constraints for cascading deletes; updated Prisma schema with related models and relationships.
scripts/generate-end-user.ts, business/business.controller.external.ts, business/business.controller.ts Removed documents field/parameter from function signatures and data objects in business creation and update endpoints.
document-file/*, document/* (controllers, modules, repositories, services, DTOs) Introduced DocumentModule and DocumentFileModule with new controllers, services, repositories, and DTO schemas to manage documents and associated file data.
providers/file/file.module.ts, providers/file/file.service.ts, src/storage/* Added a new FileModule with updated providers; introduced the uploadNewFile method in FileService; updated StorageModule (with forwardRef) and StorageService for improved error handling; removed file-service.module.ts.
workflow/* Modified WorkflowModule to import FileModule and removed FileService/FileRepository from providers/exports; added FileService import in WorkflowService.
app.module.ts Integrated DocumentModule into the main application module.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant DocumentController
    participant DocumentService
    participant DocumentRepository

    Client->>DocumentController: Send createDocument request with data and file
    DocumentController->>DocumentService: Forward createDocument(data, file)
    DocumentService->>DocumentRepository: Create new Document record
    DocumentRepository-->>DocumentService: Return created Document
    DocumentService-->>DocumentController: Forward response with Document info
    DocumentController-->>Client: Return success response
Loading
sequenceDiagram
    participant Client
    participant FileService
    participant CustomerService
    participant StorageService

    Client->>FileService: Call uploadNewFile(projectId, workflowRuntimeData, file)
    FileService->>CustomerService: Fetch customer for projectId
    CustomerService-->>FileService: Return customer details
    FileService->>StorageService: Request file transfer with processed filename
    StorageService-->>FileService: Return file storage details (e.g., URL)
    FileService-->>Client: Return upload success with file info
Loading

Suggested reviewers

  • tomer-shvadron

Poem

I'm a rabbit in the code, hopping with delight,
Schemas bloom with tables new and enums so bright.
Files and docs now dance in a modular parade,
Bugs scurry away as the legacy starts to fade.
With every commit and step, our garden grows tight,
Hop along, dear coder, into a future shining light!
🐇✨

✨ 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
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 (14)
services/workflows-service/src/document/document.controller.external.ts (3)

37-107: Return only newly created document to reduce redundant queries.
Currently, after creating a new document, the method fetches and returns all documents for the given entity, which can be costly when the entity holds a large number of documents. Consider returning only the newly created document (and its related file info) for improved efficiency and clarity.


140-166: Optimize by returning only the updated document.
Similar to the create method, the current design fetches and returns all documents for the project upon updating a single one. Consider returning just the updated document to reduce database load and response size.


168-189: Consider returning minimal info after bulk deletions.
After deleting documents, the service returns the entire set of remaining documents, which could be inefficient. Restricting the response to confirm which documents were removed or returning a success status might be more performant.

services/workflows-service/src/document/document.service.ts (3)

24-108: Ensure atomicity by leveraging transactions where possible.
Wrapping file upload and the subsequent repository operations within a single transaction ensures data consistency if any step fails. Consider invoking a transaction by default for critical create flows.


138-162: Return the updated document rather than fetching all documents.
To improve efficiency, call a repository method that returns just the updated document and its files, instead of retrieving the entire set post-update.


164-187: Limit the scope of returned data after deletions.
Fetching and returning all documents once deletions complete can significantly impact performance. Restricting the result to confirm deletion success or returning only the affected items will optimize bandwidth and client-side handling.

services/workflows-service/src/storage/storage.module.ts (1)

1-1: Consider refactoring the circular dependency between StorageModule and FileModule.

While forwardRef resolves the circular dependency, it might indicate a need for restructuring. Consider:

  1. Extracting shared functionality into a new module
  2. Reviewing the responsibilities of each module to ensure proper separation of concerns
  3. Using events/message patterns instead of direct dependencies

This would improve maintainability and testability of the code.

Also applies to: 9-9, 12-12

services/workflows-service/src/document/dtos/document.dto.ts (1)

4-18: Consider adding field validations and documentation.

While the schema is well-structured, consider:

  1. Adding validation for issuingVersion format
  2. Adding min/max constraints for version
  3. Documenting the expected structure of properties

Example improvements:

 export const DocumentSchema = Type.Object({
   id: Type.String(),
   category: Type.String(),
   type: Type.String(),
-  issuingVersion: Type.String(),
+  issuingVersion: Type.String({ pattern: '^\\d+\\.\\d+\\.\\d+$' }), // Semantic version format
   issuingCountry: Type.String(),
-  version: Type.Integer(),
+  version: Type.Integer({ minimum: 1 }), // Version should be positive
   status: Type.Enum(DocumentStatus),
   decision: Type.Optional(Type.Enum(DocumentDecision)),
-  properties: Type.Record(Type.String(), Type.Any()),
+  // Properties schema for document-specific metadata
+  properties: Type.Record(Type.String(), Type.Any(), {
+    description: 'Document-specific metadata key-value pairs'
+  }),
   businessId: Type.Optional(Type.String()),
   endUserId: Type.Optional(Type.String()),
   workflowRuntimeDataId: Type.Optional(Type.String()),
   projectId: Type.String(),
 });
services/workflows-service/src/document-file/dtos/document-file.dto.ts (1)

5-13: LGTM! Well-structured schema definition.

The schema properly defines all required fields with appropriate types and uses Prisma enums for type safety.

Consider adding string validation rules (e.g., min/max length, format) for id, documentId, fileId, and projectId fields to ensure data quality.

 export const DocumentFileSchema = Type.Object({
-  id: Type.String(),
+  id: Type.String({ minLength: 1, maxLength: 255 }),
-  documentId: Type.String(),
+  documentId: Type.String({ minLength: 1, maxLength: 255 }),
-  fileId: Type.String(),
+  fileId: Type.String({ minLength: 1, maxLength: 255 }),
-  projectId: Type.String(),
+  projectId: Type.String({ minLength: 1, maxLength: 255 }),
 });
services/workflows-service/src/document-file/document-file.service.ts (1)

10-61: LGTM! Well-implemented service with proper transaction support.

The service follows good practices:

  • Clean delegation to repository
  • Consistent method signatures
  • Transaction support

Consider adding error handling and logging for repository operations:

 async create(
   data: Prisma.DocumentFileUncheckedCreateInput,
   args?: Prisma.DocumentFileCreateArgs,
   transaction?: PrismaTransactionClient,
 ) {
+  try {
     return await this.repository.create(data, args, transaction);
+  } catch (error) {
+    // Log the error with context
+    throw new Error(`Failed to create document file: ${error.message}`);
+  }
 }
services/workflows-service/src/document/document.repository.ts (1)

35-51: Consider improving type safety for entity handling.

The findByEntityIdAndWorkflowId method uses a generic entityId that could be either a business or end user ID. Consider using a discriminated union type to make this distinction explicit.

type EntityReference = 
  | { type: 'business'; businessId: string }
  | { type: 'endUser'; endUserId: string };

async findByEntityIdAndWorkflowId(
  entity: EntityReference,
  workflowRuntimeDataId: string,
  // ... rest of the parameters
) {
  return transaction.document.findMany({
    ...args,
    where: {
      ...args?.where,
      ...(entity.type === 'business' 
        ? { businessId: entity.businessId }
        : { endUserId: entity.endUserId }),
      workflowRuntimeDataId,
      projectId: { in: projectIds },
    },
  });
}
services/workflows-service/src/document-file/document-file.repository.ts (1)

66-96: Consider adding optimistic concurrency control for delete operations.

The delete operations use deleteMany which doesn't provide feedback on the number of affected rows. Consider adding version tracking for optimistic concurrency control.

 async deleteById(
   id: string,
   projectIds: TProjectId[],
   args?: Prisma.DocumentFileDeleteManyArgs,
   transaction: PrismaTransactionClient = this.prismaService,
 ) {
-  return transaction.documentFile.deleteMany({
+  const result = await transaction.documentFile.deleteMany({
     ...args,
     where: {
       ...args?.where,
       id,
       projectId: { in: projectIds },
     },
   });
+  if (result.count === 0) {
+    throw new Error('Document file not found or was already deleted');
+  }
+  return result;
 }
services/workflows-service/src/storage/storage.service.ts (1)

21-21: Remove unused import.

The randomUUID import is not used in this file.

-import { randomUUID } from 'crypto';
services/workflows-service/src/providers/file/file.service.ts (1)

362-393: Consider adding file validation.

Add validation for file size and type to prevent potential security issues and ensure data integrity.

 async uploadNewFile(
   projectId: string,
   workflowRuntimeData: WorkflowRuntimeData,
   file: Express.Multer.File,
 ) {
+  // Validate file size (e.g., max 10MB)
+  const maxSize = 10 * 1024 * 1024; // 10MB
+  if (file.size > maxSize) {
+    throw new BadRequestException('File size exceeds maximum limit');
+  }
+
+  // Validate file type
+  const allowedTypes = ['image/jpeg', 'image/png', 'application/pdf'];
+  if (!allowedTypes.includes(file.mimetype)) {
+    throw new BadRequestException('Invalid file type');
+  }
+
   // upload file into a customer folder
   const customer = await this.customerService.getByProjectId(projectId);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between daf6947 and 2f4cbdd.

📒 Files selected for processing (25)
  • services/workflows-service/prisma/data-migrations (1 hunks)
  • services/workflows-service/prisma/migrations/20250129142137_documents_init/migration.sql (1 hunks)
  • services/workflows-service/prisma/migrations/20250129151319_documents_project/migration.sql (1 hunks)
  • services/workflows-service/prisma/migrations/20250129160127_documents_issuing_country/migration.sql (1 hunks)
  • services/workflows-service/prisma/schema.prisma (6 hunks)
  • services/workflows-service/scripts/generate-end-user.ts (0 hunks)
  • services/workflows-service/src/app.module.ts (2 hunks)
  • services/workflows-service/src/business/business.controller.external.ts (0 hunks)
  • services/workflows-service/src/business/business.controller.ts (0 hunks)
  • services/workflows-service/src/document-file/document-file.module.ts (1 hunks)
  • services/workflows-service/src/document-file/document-file.repository.ts (1 hunks)
  • services/workflows-service/src/document-file/document-file.service.ts (1 hunks)
  • services/workflows-service/src/document-file/dtos/document-file.dto.ts (1 hunks)
  • services/workflows-service/src/document/document.controller.external.ts (1 hunks)
  • services/workflows-service/src/document/document.module.ts (1 hunks)
  • services/workflows-service/src/document/document.repository.ts (1 hunks)
  • services/workflows-service/src/document/document.service.ts (1 hunks)
  • services/workflows-service/src/document/dtos/document.dto.ts (1 hunks)
  • services/workflows-service/src/providers/file/file-service.module.ts (0 hunks)
  • services/workflows-service/src/providers/file/file.module.ts (1 hunks)
  • services/workflows-service/src/providers/file/file.service.ts (3 hunks)
  • services/workflows-service/src/storage/storage.module.ts (1 hunks)
  • services/workflows-service/src/storage/storage.service.ts (2 hunks)
  • services/workflows-service/src/workflow/workflow.module.ts (2 hunks)
  • services/workflows-service/src/workflow/workflow.service.ts (1 hunks)
💤 Files with no reviewable changes (4)
  • services/workflows-service/src/business/business.controller.ts
  • services/workflows-service/src/providers/file/file-service.module.ts
  • services/workflows-service/scripts/generate-end-user.ts
  • services/workflows-service/src/business/business.controller.external.ts
✅ Files skipped from review due to trivial changes (2)
  • services/workflows-service/src/workflow/workflow.service.ts
  • services/workflows-service/prisma/data-migrations
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: test_windows
  • GitHub Check: test_linux
  • GitHub Check: build (windows-latest)
🔇 Additional comments (31)
services/workflows-service/src/document/document.controller.external.ts (1)

109-138: Straightforward retrieval logic.
The endpoint name and method logic are clear and consistent with documented functionality. No issues found.

services/workflows-service/src/document/document.service.ts (2)

110-136: Well-structured retrieval logic.
Fetching documents along with their file info and returning signed URLs is implemented cleanly. No major issues observed.


189-220: Concurrency approach is solid.
Using nested Promise.all to process files concurrently is a good pattern. The code is readable and matches common best practices for handling concurrent I/O operations.

services/workflows-service/src/document-file/document-file.module.ts (1)

6-11: Module structure is clearly defined.
The module imports the necessary Prisma module, provides the service and repository, and exports the service for external use. No issues found.

services/workflows-service/src/document/document.module.ts (1)

1-16: Well-structured module following NestJS best practices!

The module demonstrates clear separation of concerns with dedicated controller, service, and repository layers. Dependencies are properly injected and only necessary components are exported.

services/workflows-service/src/providers/file/file.module.ts (2)

1-9: Well-structured module following NestJS best practices!

The module demonstrates clear separation of concerns and proper dependency injection setup.

Also applies to: 16-20


11-15: Configure HTTP retry mechanism.

The TODO comment indicates that HTTP retry mechanism configuration is pending. This is important for handling transient failures in HTTP calls.

Would you like me to help implement the retry mechanism configuration for HTTP calls? I can provide an example configuration using NestJS's built-in retry capabilities.

services/workflows-service/src/document/dtos/document.dto.ts (1)

20-26: LGTM! Well-structured derived schemas.

The derived schemas (CreateDocumentSchema, UpdateDocumentSchema, and DeleteDocumentsSchema) are properly defined using TypeBox utilities.

services/workflows-service/src/workflow/workflow.module.ts (1)

47-48: LGTM!

The module dependencies are properly configured with forwardRef to handle circular dependencies.

Also applies to: 60-60

services/workflows-service/src/app.module.ts (1)

52-52: LGTM!

The DocumentModule is properly integrated into the application's module system.

Also applies to: 137-137

services/workflows-service/src/providers/file/file.service.ts (1)

362-393: LGTM! The implementation is clean and secure.

The method properly handles file uploads with appropriate error handling and file name sanitization.

services/workflows-service/prisma/migrations/20250129160127_documents_issuing_country/migration.sql (2)

7-8: Review SQL Column Addition Command
The SQL command to add the issuingCountry column is syntactically correct. Ensure that a plan is in place for handling existing data as noted in the comments.


1-6: ⚠️ Potential issue

Attention: Column Addition Without Default Value
The warning explicitly notes that adding the non-nullable issuingCountry column without a default value may cause issues if the Document table is already populated. Please confirm that either the table is empty or that you have a plan (for example, a one-off data migration) to set the column for existing rows.

services/workflows-service/prisma/migrations/20250129151319_documents_project/migration.sql (4)

8-10: ALTER TABLE on Document
The command to add the projectId column to the Document table is correct. Again, ensure consistent handling of existing data.


11-13: ALTER TABLE on DocumentFile
The command correctly adds the projectId column to the DocumentFile table. Please double-check the consistency with your data migration strategy.


14-19: Foreign Key Constraints Addition
Foreign key constraints for projectId on both tables are well defined with appropriate actions (RESTRICT on delete and CASCADE on update). Ensure that referenced Project IDs are valid when the migration runs.


1-7: ⚠️ Potential issue

Warning on Required Column Additions Without Defaults
The script warns that adding the non-nullable projectId column to both Document and DocumentFile without default values will fail if those tables contain data. Verify that either the tables are empty or that a migration plan exists to populate these fields before enforcing NOT NULL constraints.

services/workflows-service/prisma/migrations/20250129142137_documents_init/migration.sql (6)

7-18: New ENUM Types Creation
The ENUM types (DocumentStatus, DocumentDecision, DocumentFileType, and DocumentFileVariant) are defined correctly. Confirm that their values are consistent with the application logic and Prisma schema expectations.


22-39: Creation of the Document Table
The new Document table is created with appropriate columns and a primary key. Confirm that the field types, especially for JSONB and timestamp columns, align with your application requirements and that the absence of a default value on certain fields (like foreign keys) is intentional.


41-51: Creation of the DocumentFile Table
The DocumentFile table is defined correctly with a primary key constraint. Ensure that any foreign key relationships not present in this script (handled later) match with your application model.


53-67: Index Creation for Performance Optimizations
The indexes defined on both Document and DocumentFile tables appear to be set up correctly. Verify that these indexes align with your anticipated query patterns.


68-81: Addition of Foreign Key Constraints
All foreign key constraints, including those for businessId, endUserId, and workflowRuntimeDataId on Document as well as documentId and fileId on DocumentFile, are correctly defined. Confirm that the cascading options and deletion rules match the desired behavior.


19-21: ⚠️ Potential issue

Dropping the 'documents' Column on Business
The ALTER TABLE command for dropping the documents column is properly formatted. Please verify that a backup or migration plan is in place before data is lost.

services/workflows-service/prisma/schema.prisma (8)

86-91: Addition of 'documents' Field to EndUser Model
The new documents Document[] field in the EndUser model introduces a one-to-many relationship with Document. Verify that the inverse relation (i.e. the endUserId field in the Document model) is correctly maintained and that the relation behavior (e.g. onDelete, onUpdate) is as intended.


140-143: Addition of 'documents' Field to Business Model
The addition of the documents Document[] field enhances the KYB process by associating documents with a business. Ensure that this relation is synchronized with the migration changes and that any legacy references to documents are properly refactored.


306-308: Linking Files to Document Files
The addition of the documentFiles DocumentFile[] field in the File model properly establishes the relationship with DocumentFile. Verify that queries that depend on these relations are updated accordingly.


416-418: Extending the Project Model with Document Relations
The new additions documents Document[] and documentFiles DocumentFile[] in the Project model expand the scope of associated documents and files. Confirm that these relationships are correctly referenced in your business logic and that the indexes created in the migration scripts are consistent.


955-988: New Document Model Definition
The newly added Document model is comprehensive and closely mirrors the migration script:

  • It includes all the necessary fields (e.g., issuingCountry, issuingVersion, version, etc.)
  • The relationships to Business, EndUser, WorkflowRuntimeData, and Project are correctly defined.

Double-check that the model’s field types and constraints (e.g., non-nullable fields) match the intended database schema.


990-1000: ENUM Definitions for Document Status and Decision
The enums DocumentStatus and DocumentDecision are defined correctly. Ensure that their values align with your application logic and the expectations in both the migration scripts and any business rules.


1002-1012: ENUM Definitions for Document File Types and Variants
The enums DocumentFileType and DocumentFileVariant are well defined. Verify that these definitions match the front-end or API expectations for document file metadata.


1014-1031: New DocumentFile Model Definition
The DocumentFile model is structured correctly:

  • All relations to Document and File are clearly specified.
  • The inclusion of a projectId field reinforces the link to the Project model consistently with the migration changes.

Ensure that the indexing and relation integrity meet your application requirements.

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

🧹 Nitpick comments (4)
services/workflows-service/prisma/migrations/20250202144546_added_document_file_cascade/migration.sql (1)

4-6: Review Drop Foreign Key for fileId
The second drop operation for the "fileId" foreign key is straightforward. As with the previous drop, consider using "IF EXISTS" if there’s any chance the constraint might already be absent in some environments.

services/workflows-service/prisma/schema.prisma (3)

86-90: New Relationship in EndUser Model
The addition of the documents Document[] field in the EndUser model establishes a one-to-many relationship between an end user and related documents. This enhancement aligns with the new document management requirements.

Consider also reviewing the nullable/required nature of the foreign key in the Document model to ensure it matches your business logic.


955-988: New Model: Document
A comprehensive new Document model has been introduced. It captures key fields such as category, type, issuingVersion, issuingCountry, version, and document state (with associated enums). Relationships to Business, EndUser, WorkflowRuntimeData, and Project are properly defined.

Points to consider:

  • Verify that using String for fields like category and type is ideal; in some cases, enums might provide better constraints.
  • Ensure that the optional relationships (e.g., businessId and endUserId) align with your overall data integrity rules.

1014-1031: New Model: DocumentFile
A new DocumentFile model has been added with essential fields including type, variant, and page along with defined relationships to the Document and File models. The use of onDelete: Cascade on the relations is consistent with the migration updates and ensures clean-up of orphaned records. The indexes on documentId and fileId will help optimize query performance.

Consider whether additional indexes (e.g., on projectId) might be beneficial based on your expected query patterns.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2f4cbdd and e42f2fa.

📒 Files selected for processing (2)
  • services/workflows-service/prisma/migrations/20250202144546_added_document_file_cascade/migration.sql (1 hunks)
  • services/workflows-service/prisma/schema.prisma (6 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: test_windows
  • GitHub Check: test_linux
  • GitHub Check: lint
  • GitHub Check: build (windows-latest)
  • GitHub Check: Analyze (javascript)
  • GitHub Check: build (ubuntu-latest)
🔇 Additional comments (9)
services/workflows-service/prisma/migrations/20250202144546_added_document_file_cascade/migration.sql (3)

1-3: Review Drop Foreign Key for documentId
The script correctly drops the existing foreign key constraint for the "documentId" column. Double-check in your production environment that this constraint exists or consider using an "IF EXISTS" clause for added resilience.


7-9: Review Add Foreign Key for documentId
The new foreign key for "documentId" is added with ON DELETE CASCADE and ON UPDATE CASCADE, ensuring that deletions or updates will correctly propagate. This is in line with enforcing referential integrity for document-related files.


10-12: Review Add Foreign Key for fileId
Similarly, the new constraint for "fileId" is correctly defined with cascading update and delete rules. Confirm that cascading deletions are the intended behavior for your application’s logic concerning related file deletions.

services/workflows-service/prisma/schema.prisma (6)

142-142: New Relationship in Business Model
A new documents Document[] field has been added to the Business model, which will allow business records to be associated with multiple documents (e.g., KYB documentation). This addition appears consistent with the intended data model for document management.


307-308: Addition to File Model: documentFiles Field
The File model now includes a documentFiles DocumentFile[] field. This creates a link between files and their corresponding document file records, which is necessary given the new DocumentFile model and its cascading behavior defined elsewhere.


990-994: New Enum: DocumentStatus
The DocumentStatus enum defines status values (provided, unprovided, requested) for documents. This simple enumeration seems adequate.


996-1000: New Enum: DocumentDecision
The DocumentDecision enum, with values such as approved, rejected, and revisions, is now present. Make sure these values match the decisions handled within your business logic.


1002-1006: New Enum: DocumentFileType
The DocumentFileType enum now categorizes file types (e.g., selfie, document, and other). This addition should facilitate proper type checking and documentation classification.


1008-1012: New Enum: DocumentFileVariant
The DocumentFileVariant enum differentiates between file variants such as front, back, and other. This is useful for managing multi-page or variant documents.

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e42f2fa and 3ab27ca.

📒 Files selected for processing (2)
  • services/workflows-service/src/collection-flow/collection-flow.service.ts (0 hunks)
  • services/workflows-service/src/collection-flow/controllers/collection-flow.files.controller.ts (3 hunks)
💤 Files with no reviewable changes (1)
  • services/workflows-service/src/collection-flow/collection-flow.service.ts
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: test_windows
  • GitHub Check: build (windows-latest)
  • GitHub Check: test_linux
  • GitHub Check: Analyze (javascript)
  • GitHub Check: build (ubuntu-latest)
  • GitHub Check: lint
🔇 Additional comments (3)
services/workflows-service/src/collection-flow/controllers/collection-flow.files.controller.ts (3)

24-25: LGTM!

The new imports for FileService and WorkflowService are correctly added and follow the project's import conventions.


31-36: LGTM!

The constructor is properly updated with the new dependencies, maintaining consistent access modifiers and following dependency injection best practices.


66-70: Add error handling and clarify the empty options object.

The call to getWorkflowRuntimeDataById needs improvement:

  1. Missing error handling if the workflow runtime data is not found
  2. The purpose of the empty object parameter is unclear

Could you clarify the purpose of the empty object parameter? Consider adding proper error handling:

 const workflowRuntimeData = await this.workflowService.getWorkflowRuntimeDataById(
   tokenScope.workflowRuntimeDataId,
-  {},
+  { /* what options are supported here? */ },
   [tokenScope.projectId],
 );
+if (!workflowRuntimeData) {
+  throw new errors.NotFoundException('Workflow runtime data not found');
+}

CREATE TYPE "DocumentStatus" AS ENUM ('provided', 'unprovided', 'requested');

-- CreateEnum
CREATE TYPE "DocumentDecision" AS ENUM ('approved', 'rejected', 'revisions');
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just making sure we are aligned, in the revision flow what will happen is:

  1. user upload doc 1
  2. agent will ask for reupload
  3. status changed to revisions on doc 1
  4. user upload another doc, we create doc 2 (same category and so on, but we bump the version)
  5. now we have doc 1 (v1) still in revision (which is okay i think because its kind of an audit log as well), and doc 2 (v2) in blank/new state

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am missing some details, I'll have an easier time to implement that flow separately and end-to-end.

"status" "DocumentStatus" NOT NULL,
"decision" "DocumentDecision",
"properties" JSONB NOT NULL,
"businessId" TEXT,
Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we raised this option in the planning discussion, but having a relationship table for each entity is probably the complete solution here, as it will preserve database constraints.

on the other hand, doing the migration if the future to support it should be relatively straightforward

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For properties? How would we support the various schemas?

Copy link
Collaborator

Choose a reason for hiding this comment

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

no, for entities (business, enduser..)

import { DocumentFileRepository } from './document-file.repository';
import { PrismaModule } from '@/prisma/prisma.module';

@Module({
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does DocumentFile need to have a module or live inside a document module?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is a separate repository and service. Creating a controller feels like overkill but I'd like to avoid what happened with workflow service for runtime data + workflow definition as much as I can.

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

🧹 Nitpick comments (6)
services/workflows-service/src/document-file/document-file.repository.ts (4)

10-19: Consider adding error handling.

While the implementation is correct, consider adding error handling for Prisma operations and input validation for required fields.

 async create(
   data: Prisma.DocumentFileUncheckedCreateInput,
   args?: Prisma.DocumentFileCreateArgs,
   transaction: PrismaTransactionClient = this.prismaService,
 ) {
+  try {
     return transaction.documentFile.create({
       ...args,
       data,
     });
+  } catch (error) {
+    if (error instanceof Prisma.PrismaClientKnownRequestError) {
+      // Handle specific Prisma errors (e.g., unique constraint violations)
+      throw new Error(`Failed to create document file: ${error.message}`);
+    }
+    throw error;
+  }
 }

21-30: Add error handling for bulk operations.

Similar to the create method, consider adding error handling for bulk operations.

 async createMany(
   data: Prisma.Enumerable<Prisma.DocumentFileCreateManyInput>,
   args?: Prisma.DocumentFileCreateManyArgs,
   transaction: PrismaTransactionClient = this.prismaService,
 ) {
+  try {
     return transaction.documentFile.createMany({
       ...args,
       data,
     });
+  } catch (error) {
+    if (error instanceof Prisma.PrismaClientKnownRequestError) {
+      throw new Error(`Failed to create document files in bulk: ${error.message}`);
+    }
+    throw error;
+  }
 }

64-78: Consider using delete instead of deleteMany for single ID operations.

Since you're deleting by a specific ID, consider using delete instead of deleteMany for better type safety and to ensure only one record is affected.

 async deleteById(
   id: string,
   projectIds: TProjectId[],
   args?: Prisma.DocumentFileDeleteManyArgs,
   transaction: PrismaTransactionClient = this.prismaService,
 ) {
+  if (!projectIds?.length) {
+    throw new Error('At least one project ID must be provided');
+  }
-  return transaction.documentFile.deleteMany({
+  return transaction.documentFile.delete({
     ...args,
     where: {
       ...args?.where,
       id,
       projectId: { in: projectIds },
     },
   });
 }

80-94: Add validation for projectIds array.

Similar to other methods, validate that the projectIds array is not empty before executing the delete operation.

 async deleteByDocumentId(
   documentId: string,
   projectIds: TProjectId[],
   args?: Prisma.DocumentFileDeleteManyArgs,
   transaction: PrismaTransactionClient = this.prismaService,
 ) {
+  if (!projectIds?.length) {
+    throw new Error('At least one project ID must be provided');
+  }
   return transaction.documentFile.deleteMany({
     ...args,
     where: {
       ...args?.where,
       documentId,
       projectId: { in: projectIds },
     },
   });
 }
services/workflows-service/src/document/document.controller.external.ts (1)

130-138: Consider implementing pagination for document retrieval.

The getDocumentsByEntityIdAndWorkflowId endpoint might return a large number of documents. Consider implementing pagination to improve performance and prevent memory issues.

services/workflows-service/src/document/document.service.ts (1)

196-220: Optimize batch file processing.

The nested Promise.all calls could be flattened for better performance and error handling.

-    return await Promise.all(
-      documents?.map(async document => {
-        const files = await Promise.all(
-          document.files?.map(async file => {
-            const uploadedFile = await this.storageService.fetchFileContent({
-              id: file.fileId,
-              projectIds: [document.projectId],
-              format,
-            });
+    const fileRequests = documents?.flatMap(document =>
+      (document.files ?? []).map(file => ({
+        file,
+        document,
+        promise: this.storageService.fetchFileContent({
+          id: file.fileId,
+          projectIds: [document.projectId],
+          format,
+        }),
+      }))
+    ) ?? [];

+    const uploadedFiles = await Promise.all(
+      fileRequests.map(async ({ promise }) => promise)
+    );

+    const documentsMap = new Map(
+      documents?.map(document => [document.id, { ...document, files: [] }])
+    );

+    fileRequests.forEach(({ file, document }, index) => {
+      const uploadedFile = uploadedFiles[index];
+      const documentWithFiles = documentsMap.get(document.id);
+      if (documentWithFiles) {
+        documentWithFiles.files.push({
+          ...file,
+          mimeType: uploadedFile.mimeType,
+          signedUrl: uploadedFile.signedUrl,
+        });
+      }
+    });

+    return Array.from(documentsMap.values());
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3ab27ca and b42ddb7.

📒 Files selected for processing (5)
  • apps/backoffice-v2/src/lib/blocks/hooks/useManageUbosBlock/ubos-form-json-definition.ts (2 hunks)
  • services/workflows-service/src/document-file/document-file.repository.ts (1 hunks)
  • services/workflows-service/src/document-file/document-file.service.ts (1 hunks)
  • services/workflows-service/src/document/document.controller.external.ts (1 hunks)
  • services/workflows-service/src/document/document.service.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • services/workflows-service/src/document-file/document-file.service.ts
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: build (windows-latest)
  • GitHub Check: test_windows
  • GitHub Check: test_linux
  • GitHub Check: lint
  • GitHub Check: Analyze (javascript)
  • GitHub Check: build (ubuntu-latest)
🔇 Additional comments (3)
apps/backoffice-v2/src/lib/blocks/hooks/useManageUbosBlock/ubos-form-json-definition.ts (1)

1-218: LGTM: Comprehensive UBO data collection form.

The form structure is well-designed with:

  • Comprehensive field collection for UBO information
  • Proper validation through required fields
  • Specialized UI components for specific fields (PhoneInput, DateInput, CountryPicker, NationalityPicker)
services/workflows-service/src/document-file/document-file.repository.ts (1)

1-9: LGTM! Well-structured class setup following NestJS best practices.

The implementation properly uses dependency injection and follows the repository pattern.

services/workflows-service/src/document/document.controller.external.ts (1)

37-46: 🛠️ Refactor suggestion

Consider adding file type validation in the FileInterceptor configuration.

While the file size limit is enforced, there's no explicit file type validation in the interceptor configuration. This could potentially allow upload of malicious files.

Let's verify the file filter implementation:

@Omri-Levy Omri-Levy changed the base branch from dev to epic/feat/documents-tracker February 3, 2025 12:52
@Omri-Levy Omri-Levy merged commit 8f7dfc9 into epic/feat/documents-tracker Feb 4, 2025
17 of 18 checks passed
@Omri-Levy Omri-Levy deleted the bal-3473 branch February 4, 2025 09:00
chesterkmr added a commit that referenced this pull request Feb 9, 2025
* feat(workflows-service): implemented document controller, service, repository, and dto

* fix(workflows-service): added cascase on delete

* refactor(workflows-service): removed uploadFile method from collection flow service

* feat(workflows-service): added the ability to reupload document (#3019)

* feat: implemented documents upload

* feat: reworked creation ui

* feat: implemented document creation & deletion

* feat: finalized entity group field

* fix: fixed tests

* fix: cleanup

* fix: format fix

* fix: fixed build

---------

Co-authored-by: Omri Levy <[email protected]>
Co-authored-by: Omri Levy <[email protected]>
Co-authored-by: Shane <[email protected]>
@coderabbitai coderabbitai bot mentioned this pull request Feb 9, 2025
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