# CategoryService

**Kind:** Service

**Source:** [`atloria-monorepo/apps/api/src/document/category.service.ts`](https://github.com/sherkety/atloria/blob/main/atloria-monorepo/apps/api/src/document/category.service.ts#L14)

`CategoryService` manages document categories in the API layer. It provides CRUD operations, category reordering, and tree retrieval so controllers can expose both flat management workflows and hierarchical navigation structures.

## Methods

| Method | Signature | Returns | Description |
|---|---|---|---|
| `create` | `create(dto: CreateCategoryDto, user: JwtPayload)` | `unknown` | Create a new category |
| `list` | `list(filters: CategoryFiltersDto, user: JwtPayload)` | `unknown` | List categories with filters |
| `get` | `get(id: string, user: JwtPayload)` | `unknown` | Get a single category by ID |
| `update` | `update(id: string, dto: UpdateCategoryDto, user: JwtPayload)` | `unknown` | Update a category |
| `delete` | `delete(id: string, user: JwtPayload)` | `unknown` | Delete a category |
| `reorder` | `reorder(categoryIds: string[], user: JwtPayload)` | `unknown` | Reorder categories |
| `getTree` | `getTree(projectId: string, user: JwtPayload, docVersionId: string)` | `unknown` | Get category tree structure for a project |

## Dependencies

- `PrismaService`

## Where it refuses work

- `CategoryService` stops the work with `NotFoundException` when `!project` — “Project not found”, in 3 places.
- `CategoryService` stops the work with `NotFoundException` when `!category` — “Category not found”, in 3 places.
- `CategoryService` stops the work with `ForbiddenException` when `category.project.organizationId !== user.organizationId` — “You do not have access to this category”, in 3 places.
- `CategoryService` stops the work with `NotFoundException` when `!parentCategory` — “Parent category not found”, in 2 places.
- `CategoryService` stops the work with `NotFoundException` when `!document` — “Default document not found”, in 2 places.
- `CategoryService` stops the work with `ForbiddenException` when `project.organizationId !== user.organizationId` — “You do not have access to this project”.

## Diagram

```mermaid
sequenceDiagram
  participant Client
  participant Controller as Category Controller
  participant Service as CategoryService
  participant Repository as Category Repository/Database

  Client->>Controller: Create, update, list, or reorder category
  Controller->>Service: Call CategoryService method
  Service->>Repository: Read or persist category data
  Repository-->>Service: Category records
  Service-->>Controller: Category or category tree
  Controller-->>Client: API response

  Client->>Controller: Get category tree
  Controller->>Service: getTree()
  Service->>Repository: Load categories and parent relations
  Repository-->>Service: Flat category records
  Service-->>Controller: Hierarchical category tree
  Controller-->>Client: Tree response
```

## Usage

```ts
import { Injectable } from '@nestjs/common';
import { CategoryService } from './category.service';

@Injectable()
export class DocumentCategoryFacade {
  constructor(private readonly categoryService: CategoryService) {}

  async createAndLoadTree(documentId: string) {
    await this.categoryService.create({
      documentId,
      name: 'Architecture',
      parentId: null,
    });

    return this.categoryService.getTree({
      documentId,
    });
  }

  async moveCategory(categoryId: string, position: number) {
    return this.categoryService.reorder({
      categoryId,
      position,
    });
  }
}
```

## AI Coding Instructions

- Use `getTree()` when rendering nested category navigation; avoid rebuilding hierarchy independently in controllers or clients.
- Keep category mutations (`create`, `update`, `delete`, and `reorder`) inside `CategoryService` so validation and persistence rules remain centralized.
- Validate parent/category ownership against the relevant document or workspace before creating, moving, or reordering categories.
- When changing ordering behavior, update `reorder()` atomically to prevent duplicate positions or inconsistent sibling ordering.
- Preserve existing NestJS dependency-injection patterns and call the service through controllers or other injected providers rather than instantiating it directly.

## Relationships

- DEPENDS_ON → `PrismaService`

## Referenced By

- `CategoryController` (DEPENDS_ON)
- `DocumentModule` (MODULE_PROVIDES)
- `DocumentModule` (MODULE_EXPORTS)
