# TRACEABILITY-MGN-011.yaml
# Matriz de Trazabilidad - MGN-011: Proyectos Genéricos
# Fecha: 2025-11-24
# Versión: 1.0

module:
  id: MGN-011
  name: "Proyectos Genéricos"
  description: "Gestión de proyectos: tareas, milestones, timesheet, miembros y seguimiento"
  priority: P1
  story_points: 40
  status: Diseñado

metadata:
  total_rf: 5
  total_et_backend: 5
  total_et_frontend: 5
  total_tables: 5
  total_tests: 100
  coverage: 100%

requirements:
  - rf_id: RF-MGN-011-001
    rf_title: "Gestión de Proyectos"
    rf_file: "requerimientos-funcionales/mgn-011/RF-MGN-011-001-gestión-de-proyectos.md"
    priority: P1
    story_points: 8

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-011/ET-BACKEND-MGN-011-001-gestión-de-proyectos.md"
      endpoints:
        - method: POST
          path: /api/v1/projects
          description: "Crear nuevo proyecto"
        - method: GET
          path: /api/v1/projects
          description: "Listar todos los proyectos"
        - method: GET
          path: /api/v1/projects/:id
          description: "Obtener proyecto por ID"
        - method: PUT
          path: /api/v1/projects/:id
          description: "Actualizar proyecto"
        - method: DELETE
          path: /api/v1/projects/:id
          description: "Eliminar proyecto (soft delete)"
      services:
        - name: "ProjectService"
          file: "src/modules/projects/services/project.service.ts"
          methods:
            - create
            - findAll
            - findOne
            - update
            - remove
            - validateBusinessRules
      controllers:
        - name: "ProjectController"
          file: "src/modules/projects/controllers/project.controller.ts"
      dtos:
        - name: "CreateProjectDto"
          file: "src/modules/projects/dto/create-project.dto.ts"
        - name: "UpdateProjectDto"
          file: "src/modules/projects/dto/update-project.dto.ts"
        - name: "ProjectResponseDto"
          file: "src/modules/projects/dto/project-response.dto.ts"
        - name: "FilterProjectDto"
          file: "src/modules/projects/dto/filter-project.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-011/ET-FRONTEND-MGN-011-001-gestión-de-proyectos.md"
      routes:
        - path: "/projects"
          component: "ProjectsPage"
        - path: "/projects/create"
          component: "CreateProjectPage"
        - path: "/projects/:id/edit"
          component: "EditProjectPage"
        - path: "/projects/:id"
          component: "ViewProjectPage"
      components:
        - name: "ProjectsTable"
          file: "src/widgets/projects-table/ui/ProjectsTable.tsx"
          type: widget
        - name: "CreateProjectForm"
          file: "src/features/create-project/ui/CreateProjectForm.tsx"
          type: feature
        - name: "ProjectCard"
          file: "src/entities/project/ui/ProjectCard.tsx"
          type: entity
        - name: "ProjectPage"
          file: "src/pages/projects/ProjectPage.tsx"
          type: page
      api_client:
        - name: "projectApi"
          file: "src/entities/project/api/project.api.ts"
          methods:
            - getAll
            - getById
            - create
            - update
            - delete
      state_management:
        - name: "useProjectStore"
          file: "src/entities/project/model/project.store.ts"
          type: zustand
        - name: "useProjects"
          file: "src/entities/project/api/project.queries.ts"
          type: react-query

    database_tables:
      - schema: projects
        table: projects
        file: "database-design/schemas/projects-schema-ddl.sql"
        operations:
          - SELECT
          - INSERT
          - UPDATE
          - DELETE (soft)
        indices:
          - idx_projects_tenant_id
          - idx_projects_analytic_account_id
          - idx_projects_status
        rls_policy: tenant_isolation_projects

    tests:
      backend:
        unit_tests:
          - file: "src/modules/projects/services/project.service.spec.ts"
            test_cases:
              - "should create project with valid data"
              - "should link to analytic account automatically"
              - "should validate date range"
              - "should find all projects for tenant"
              - "should update project successfully"
        integration_tests:
          - file: "test/projects/project.controller.e2e-spec.ts"
            test_cases:
              - "POST /api/v1/projects should create project"
              - "GET /api/v1/projects should return all projects"
              - "GET /api/v1/projects/:id should return project"
              - "PUT /api/v1/projects/:id should update project"
              - "DELETE /api/v1/projects/:id should soft delete project"
              - "should enforce tenant isolation"
              - "should require authentication"
              - "should check permissions"
      frontend:
        component_tests:
          - file: "src/widgets/projects-table/ui/ProjectsTable.test.tsx"
            test_cases:
              - "should render table with projects"
              - "should handle pagination"
              - "should filter by status"
          - file: "src/features/create-project/ui/CreateProjectForm.test.tsx"
            test_cases:
              - "should validate required fields"
              - "should submit valid form"
              - "should show error messages"
        e2e_tests:
          - file: "e2e/projects/projects.spec.ts"
            test_cases:
              - "should create project successfully"
              - "should edit project successfully"
              - "should delete project with confirmation"
              - "should enforce permissions"

    acceptance_criteria:
      - id: AC-001
        description: "Usuario puede crear proyectos con nombre, fechas y presupuesto"
        status: Pending
        test_reference: "test/projects/project.controller.e2e-spec.ts:35"
      - id: AC-002
        description: "Proyecto se vincula automáticamente a cuenta analítica"
        status: Pending
        test_reference: "src/modules/projects/services/project.service.spec.ts:72"
      - id: AC-003
        description: "Sistema calcula progreso basado en tareas completadas"
        status: Pending
        test_reference: "test/projects/project.controller.e2e-spec.ts:108"

    business_rules:
      - id: RN-001
        description: "Fecha de fin debe ser posterior a fecha de inicio"
        implementation: "src/modules/projects/dto/create-project.dto.ts:@IsDateAfter('start_date')"
        test_reference: "src/modules/projects/services/project.service.spec.ts:95"
      - id: RN-002
        description: "Proyecto crea automáticamente cuenta analítica asociada"
        implementation: "src/modules/projects/services/project.service.ts:create()"
        test_reference: "src/modules/projects/services/project.service.spec.ts:122"
      - id: RN-003
        description: "Progreso se calcula como: tareas completadas / total tareas"
        implementation: "src/modules/projects/services/project.service.ts:calculateProgress()"
        test_reference: "src/modules/projects/services/project.service.spec.ts:148"

    dependencies:
      rf_dependencies:
        - RF-MGN-008-001
      module_dependencies:
        - MGN-001
        - MGN-008
      external_dependencies:
        - name: "@nestjs/common"
          version: "^10.0.0"
        - name: "ant-design"
          version: "^5.0.0"

  - rf_id: RF-MGN-011-002
    rf_title: "Gestión de Tareas (Kanban)"
    rf_file: "requerimientos-funcionales/mgn-011/RF-MGN-011-002-gestión-de-tareas-kanban.md"
    priority: P1
    story_points: 13

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-011/ET-BACKEND-MGN-011-002-gestión-de-tareas-kanban.md"
      endpoints:
        - method: POST
          path: /api/v1/projects/tasks
          description: "Crear nueva tarea"
        - method: GET
          path: /api/v1/projects/tasks
          description: "Listar todas las tareas"
        - method: GET
          path: /api/v1/projects/tasks/:id
          description: "Obtener tarea por ID"
        - method: PUT
          path: /api/v1/projects/tasks/:id
          description: "Actualizar tarea"
        - method: POST
          path: /api/v1/projects/tasks/:id/move
          description: "Mover tarea a otro stage"
      services:
        - name: "TaskService"
          file: "src/modules/projects/services/task.service.ts"
          methods:
            - create
            - findAll
            - findOne
            - update
            - move
            - validateBusinessRules
      controllers:
        - name: "TaskController"
          file: "src/modules/projects/controllers/task.controller.ts"
      dtos:
        - name: "CreateTaskDto"
          file: "src/modules/projects/dto/create-task.dto.ts"
        - name: "UpdateTaskDto"
          file: "src/modules/projects/dto/update-task.dto.ts"
        - name: "TaskResponseDto"
          file: "src/modules/projects/dto/task-response.dto.ts"
        - name: "MoveTaskDto"
          file: "src/modules/projects/dto/move-task.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-011/ET-FRONTEND-MGN-011-002-gestión-de-tareas-kanban.md"
      routes:
        - path: "/projects/:projectId/tasks"
          component: "ProjectTasksPage"
        - path: "/projects/:projectId/tasks/kanban"
          component: "TasksKanbanPage"
        - path: "/projects/tasks/:id"
          component: "ViewTaskPage"
      components:
        - name: "TasksKanban"
          file: "src/widgets/tasks-kanban/ui/TasksKanban.tsx"
          type: widget
        - name: "CreateTaskForm"
          file: "src/features/create-task/ui/CreateTaskForm.tsx"
          type: feature
        - name: "TaskCard"
          file: "src/entities/task/ui/TaskCard.tsx"
          type: entity
        - name: "TaskPage"
          file: "src/pages/projects/TaskPage.tsx"
          type: page
      api_client:
        - name: "taskApi"
          file: "src/entities/task/api/task.api.ts"
          methods:
            - getAll
            - getById
            - create
            - update
            - move
      state_management:
        - name: "useTaskStore"
          file: "src/entities/task/model/task.store.ts"
          type: zustand
        - name: "useTasks"
          file: "src/entities/task/api/task.queries.ts"
          type: react-query

    database_tables:
      - schema: projects
        table: tasks
        file: "database-design/schemas/projects-schema-ddl.sql"
        operations:
          - SELECT
          - INSERT
          - UPDATE
          - DELETE (soft)
        indices:
          - idx_tasks_tenant_id
          - idx_tasks_project_id
          - idx_tasks_stage_id
          - idx_tasks_assigned_to
        rls_policy: tenant_isolation_tasks
      - schema: projects
        table: task_stages
        file: "database-design/schemas/projects-schema-ddl.sql"
        operations:
          - SELECT
          - INSERT
          - UPDATE
        indices:
          - idx_task_stages_project_id
        rls_policy: tenant_isolation_task_stages

    tests:
      backend:
        unit_tests:
          - file: "src/modules/projects/services/task.service.spec.ts"
            test_cases:
              - "should create task with valid data"
              - "should assign task to user"
              - "should move task between stages"
              - "should find all tasks for project"
              - "should update task successfully"
        integration_tests:
          - file: "test/projects/task.controller.e2e-spec.ts"
            test_cases:
              - "POST /api/v1/projects/tasks should create task"
              - "GET /api/v1/projects/tasks should return all tasks"
              - "GET /api/v1/projects/tasks/:id should return task"
              - "PUT /api/v1/projects/tasks/:id should update task"
              - "POST /api/v1/projects/tasks/:id/move should move task"
              - "should enforce tenant isolation"
              - "should require authentication"
              - "should check permissions"
      frontend:
        component_tests:
          - file: "src/widgets/tasks-kanban/ui/TasksKanban.test.tsx"
            test_cases:
              - "should render kanban board"
              - "should drag and drop tasks"
              - "should show task details"
          - file: "src/features/create-task/ui/CreateTaskForm.test.tsx"
            test_cases:
              - "should validate required fields"
              - "should submit valid form"
              - "should show error messages"
        e2e_tests:
          - file: "e2e/projects/tasks.spec.ts"
            test_cases:
              - "should create task successfully"
              - "should drag task to new stage"
              - "should assign task to user"
              - "should enforce permissions"

    acceptance_criteria:
      - id: AC-001
        description: "Usuario puede crear tareas dentro de proyectos"
        status: Pending
        test_reference: "test/projects/task.controller.e2e-spec.ts:42"
      - id: AC-002
        description: "Tareas se visualizan en formato Kanban"
        status: Pending
        test_reference: "src/widgets/tasks-kanban/ui/TasksKanban.test.tsx:78"
      - id: AC-003
        description: "Tareas se mueven entre stages con drag & drop"
        status: Pending
        test_reference: "e2e/projects/tasks.spec.ts:115"

    business_rules:
      - id: RN-001
        description: "Tarea debe estar asociada a un proyecto"
        implementation: "src/modules/projects/services/task.service.ts:validateProject()"
        test_reference: "src/modules/projects/services/task.service.spec.ts:102"
      - id: RN-002
        description: "Al mover tarea, se registra actividad automáticamente"
        implementation: "src/modules/projects/services/task.service.ts:move()"
        test_reference: "src/modules/projects/services/task.service.spec.ts:128"
      - id: RN-003
        description: "Tarea completada actualiza progreso del proyecto"
        implementation: "src/modules/projects/services/task.service.ts:updateProgress()"
        test_reference: "src/modules/projects/services/task.service.spec.ts:155"

    dependencies:
      rf_dependencies:
        - RF-MGN-011-001
      module_dependencies:
        - MGN-001
        - MGN-014
      external_dependencies:
        - name: "@dnd-kit/core"
          version: "^6.0.0"

  - rf_id: RF-MGN-011-003
    rf_title: "Milestones (Hitos)"
    rf_file: "requerimientos-funcionales/mgn-011/RF-MGN-011-003-milestones-hitos.md"
    priority: P1
    story_points: 3

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-011/ET-BACKEND-MGN-011-003-milestones-hitos.md"
      endpoints:
        - method: POST
          path: /api/v1/projects/milestones
          description: "Crear milestone"
        - method: GET
          path: /api/v1/projects/milestones
          description: "Listar milestones"
        - method: GET
          path: /api/v1/projects/milestones/:id
          description: "Obtener milestone por ID"
        - method: PUT
          path: /api/v1/projects/milestones/:id
          description: "Actualizar milestone"
        - method: POST
          path: /api/v1/projects/milestones/:id/complete
          description: "Marcar milestone como completado"
      services:
        - name: "MilestoneService"
          file: "src/modules/projects/services/milestone.service.ts"
          methods:
            - create
            - findAll
            - findOne
            - update
            - complete
            - validateBusinessRules
      controllers:
        - name: "MilestoneController"
          file: "src/modules/projects/controllers/milestone.controller.ts"
      dtos:
        - name: "CreateMilestoneDto"
          file: "src/modules/projects/dto/create-milestone.dto.ts"
        - name: "UpdateMilestoneDto"
          file: "src/modules/projects/dto/update-milestone.dto.ts"
        - name: "MilestoneResponseDto"
          file: "src/modules/projects/dto/milestone-response.dto.ts"
        - name: "FilterMilestoneDto"
          file: "src/modules/projects/dto/filter-milestone.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-011/ET-FRONTEND-MGN-011-003-milestones-hitos.md"
      routes:
        - path: "/projects/:projectId/milestones"
          component: "MilestonesPage"
        - path: "/projects/milestones/:id"
          component: "ViewMilestonePage"
      components:
        - name: "MilestonesTimeline"
          file: "src/widgets/milestones-timeline/ui/MilestonesTimeline.tsx"
          type: widget
        - name: "CreateMilestoneForm"
          file: "src/features/create-milestone/ui/CreateMilestoneForm.tsx"
          type: feature
        - name: "MilestoneCard"
          file: "src/entities/milestone/ui/MilestoneCard.tsx"
          type: entity
        - name: "MilestonePage"
          file: "src/pages/projects/MilestonePage.tsx"
          type: page
      api_client:
        - name: "milestoneApi"
          file: "src/entities/milestone/api/milestone.api.ts"
          methods:
            - getAll
            - getById
            - create
            - update
            - complete
      state_management:
        - name: "useMilestoneStore"
          file: "src/entities/milestone/model/milestone.store.ts"
          type: zustand
        - name: "useMilestones"
          file: "src/entities/milestone/api/milestone.queries.ts"
          type: react-query

    database_tables:
      - schema: projects
        table: milestones
        file: "database-design/schemas/projects-schema-ddl.sql"
        operations:
          - SELECT
          - INSERT
          - UPDATE
          - DELETE (soft)
        indices:
          - idx_milestones_tenant_id
          - idx_milestones_project_id
          - idx_milestones_target_date
        rls_policy: tenant_isolation_milestones

    tests:
      backend:
        unit_tests:
          - file: "src/modules/projects/services/milestone.service.spec.ts"
            test_cases:
              - "should create milestone with valid data"
              - "should validate target date"
              - "should complete milestone successfully"
              - "should find all milestones for project"
              - "should update milestone successfully"
        integration_tests:
          - file: "test/projects/milestone.controller.e2e-spec.ts"
            test_cases:
              - "POST /api/v1/projects/milestones should create milestone"
              - "GET /api/v1/projects/milestones should return all milestones"
              - "GET /api/v1/projects/milestones/:id should return milestone"
              - "PUT /api/v1/projects/milestones/:id should update milestone"
              - "POST /api/v1/projects/milestones/:id/complete should complete"
              - "should enforce tenant isolation"
              - "should require authentication"
              - "should check permissions"
      frontend:
        component_tests:
          - file: "src/widgets/milestones-timeline/ui/MilestonesTimeline.test.tsx"
            test_cases:
              - "should render timeline"
              - "should show completed milestones"
              - "should highlight overdue milestones"
          - file: "src/features/create-milestone/ui/CreateMilestoneForm.test.tsx"
            test_cases:
              - "should validate required fields"
              - "should submit valid form"
              - "should show error messages"
        e2e_tests:
          - file: "e2e/projects/milestones.spec.ts"
            test_cases:
              - "should create milestone successfully"
              - "should complete milestone"
              - "should view milestones timeline"
              - "should enforce permissions"

    acceptance_criteria:
      - id: AC-001
        description: "Usuario puede crear milestones con nombre y fecha objetivo"
        status: Pending
        test_reference: "test/projects/milestone.controller.e2e-spec.ts:45"
      - id: AC-002
        description: "Milestones se visualizan en timeline del proyecto"
        status: Pending
        test_reference: "src/widgets/milestones-timeline/ui/MilestonesTimeline.test.tsx:82"
      - id: AC-003
        description: "Sistema alerta sobre milestones próximos o vencidos"
        status: Pending
        test_reference: "e2e/projects/milestones.spec.ts:118"

    business_rules:
      - id: RN-001
        description: "Milestone debe estar asociado a un proyecto"
        implementation: "src/modules/projects/services/milestone.service.ts:validateProject()"
        test_reference: "src/modules/projects/services/milestone.service.spec.ts:108"
      - id: RN-002
        description: "Fecha objetivo debe estar dentro del rango del proyecto"
        implementation: "src/modules/projects/services/milestone.service.ts:validateDate()"
        test_reference: "src/modules/projects/services/milestone.service.spec.ts:135"
      - id: RN-003
        description: "Completar milestone actualiza progreso del proyecto"
        implementation: "src/modules/projects/services/milestone.service.ts:complete()"
        test_reference: "src/modules/projects/services/milestone.service.spec.ts:162"

    dependencies:
      rf_dependencies:
        - RF-MGN-011-001
      module_dependencies:
        - MGN-001
        - MGN-014
      external_dependencies:
        - name: "@nestjs/common"
          version: "^10.0.0"

  - rf_id: RF-MGN-011-004
    rf_title: "Timesheet de Proyectos"
    rf_file: "requerimientos-funcionales/mgn-011/RF-MGN-011-004-timesheet-de-proyectos.md"
    priority: P1
    story_points: 8

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-011/ET-BACKEND-MGN-011-004-timesheet-de-proyectos.md"
      endpoints:
        - method: POST
          path: /api/v1/projects/timesheet-entries
          description: "Registrar entrada de timesheet"
        - method: GET
          path: /api/v1/projects/timesheet-entries
          description: "Listar entradas de timesheet"
        - method: GET
          path: /api/v1/projects/timesheet-entries/:id
          description: "Obtener entrada por ID"
        - method: PUT
          path: /api/v1/projects/timesheet-entries/:id
          description: "Actualizar entrada"
        - method: GET
          path: /api/v1/projects/timesheet-entries/report
          description: "Reporte de timesheet"
      services:
        - name: "TimesheetService"
          file: "src/modules/projects/services/timesheet.service.ts"
          methods:
            - create
            - findAll
            - findOne
            - update
            - getReport
            - validateBusinessRules
      controllers:
        - name: "TimesheetController"
          file: "src/modules/projects/controllers/timesheet.controller.ts"
      dtos:
        - name: "CreateTimesheetEntryDto"
          file: "src/modules/projects/dto/create-timesheet-entry.dto.ts"
        - name: "UpdateTimesheetEntryDto"
          file: "src/modules/projects/dto/update-timesheet-entry.dto.ts"
        - name: "TimesheetEntryResponseDto"
          file: "src/modules/projects/dto/timesheet-entry-response.dto.ts"
        - name: "TimesheetReportDto"
          file: "src/modules/projects/dto/timesheet-report.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-011/ET-FRONTEND-MGN-011-004-timesheet-de-proyectos.md"
      routes:
        - path: "/projects/timesheet"
          component: "TimesheetPage"
        - path: "/projects/timesheet/report"
          component: "TimesheetReportPage"
      components:
        - name: "TimesheetGrid"
          file: "src/widgets/timesheet-grid/ui/TimesheetGrid.tsx"
          type: widget
        - name: "CreateTimesheetEntry"
          file: "src/features/create-timesheet-entry/ui/CreateTimesheetEntry.tsx"
          type: feature
        - name: "TimesheetCard"
          file: "src/entities/timesheet/ui/TimesheetCard.tsx"
          type: entity
        - name: "TimesheetPage"
          file: "src/pages/projects/TimesheetPage.tsx"
          type: page
      api_client:
        - name: "timesheetApi"
          file: "src/entities/timesheet/api/timesheet.api.ts"
          methods:
            - getAll
            - getById
            - create
            - update
            - getReport
      state_management:
        - name: "useTimesheetStore"
          file: "src/entities/timesheet/model/timesheet.store.ts"
          type: zustand
        - name: "useTimesheet"
          file: "src/entities/timesheet/api/timesheet.queries.ts"
          type: react-query

    database_tables:
      - schema: projects
        table: timesheet_entries
        file: "database-design/schemas/projects-schema-ddl.sql"
        operations:
          - SELECT
          - INSERT
          - UPDATE
          - DELETE (soft)
        indices:
          - idx_timesheet_entries_tenant_id
          - idx_timesheet_entries_project_id
          - idx_timesheet_entries_task_id
          - idx_timesheet_entries_user_id
          - idx_timesheet_entries_date
        rls_policy: tenant_isolation_timesheet_entries

    tests:
      backend:
        unit_tests:
          - file: "src/modules/projects/services/timesheet.service.spec.ts"
            test_cases:
              - "should create timesheet entry"
              - "should validate hours range"
              - "should generate timesheet report"
              - "should find all entries for user"
              - "should update entry successfully"
        integration_tests:
          - file: "test/projects/timesheet.controller.e2e-spec.ts"
            test_cases:
              - "POST /api/v1/projects/timesheet-entries should create entry"
              - "GET /api/v1/projects/timesheet-entries should return entries"
              - "GET /api/v1/projects/timesheet-entries/:id should return entry"
              - "PUT /api/v1/projects/timesheet-entries/:id should update entry"
              - "GET /api/v1/projects/timesheet-entries/report should return report"
              - "should enforce tenant isolation"
              - "should require authentication"
              - "should check permissions"
      frontend:
        component_tests:
          - file: "src/widgets/timesheet-grid/ui/TimesheetGrid.test.tsx"
            test_cases:
              - "should render timesheet grid"
              - "should edit inline hours"
              - "should calculate weekly totals"
          - file: "src/features/create-timesheet-entry/ui/CreateTimesheetEntry.test.tsx"
            test_cases:
              - "should validate hours"
              - "should submit valid entry"
              - "should show error messages"
        e2e_tests:
          - file: "e2e/projects/timesheet.spec.ts"
            test_cases:
              - "should log hours successfully"
              - "should view timesheet report"
              - "should edit timesheet entry"
              - "should enforce permissions"

    acceptance_criteria:
      - id: AC-001
        description: "Usuario puede registrar horas trabajadas en proyectos/tareas"
        status: Pending
        test_reference: "test/projects/timesheet.controller.e2e-spec.ts:48"
      - id: AC-002
        description: "Timesheet se visualiza en formato grid semanal"
        status: Pending
        test_reference: "src/widgets/timesheet-grid/ui/TimesheetGrid.test.tsx:85"
      - id: AC-003
        description: "Reportes muestran horas por proyecto/tarea/usuario"
        status: Pending
        test_reference: "e2e/projects/timesheet.spec.ts:122"

    business_rules:
      - id: RN-001
        description: "Horas registradas deben estar entre 0 y 24"
        implementation: "src/modules/projects/dto/create-timesheet-entry.dto.ts:@Min(0) @Max(24)"
        test_reference: "src/modules/projects/services/timesheet.service.spec.ts:112"
      - id: RN-002
        description: "Entrada debe estar asociada a proyecto o tarea"
        implementation: "src/modules/projects/services/timesheet.service.ts:validateRelation()"
        test_reference: "src/modules/projects/services/timesheet.service.spec.ts:138"
      - id: RN-003
        description: "Horas facturables generan líneas analíticas automáticamente"
        implementation: "src/modules/projects/services/timesheet.service.ts:createAnalyticLine()"
        test_reference: "src/modules/projects/services/timesheet.service.spec.ts:165"

    dependencies:
      rf_dependencies:
        - RF-MGN-011-001
        - RF-MGN-011-002
        - RF-MGN-008-002
      module_dependencies:
        - MGN-001
        - MGN-008
      external_dependencies:
        - name: "@nestjs/common"
          version: "^10.0.0"
        - name: "date-fns"
          version: "^2.30.0"

  - rf_id: RF-MGN-011-005
    rf_title: "Vista Gantt de Proyectos"
    rf_file: "requerimientos-funcionales/mgn-011/RF-MGN-011-005-vista-gantt-de-proyectos.md"
    priority: P2
    story_points: 8

    et_backend:
      file: "especificaciones-tecnicas/backend/mgn-011/ET-BACKEND-MGN-011-005-vista-gantt-de-proyectos.md"
      endpoints:
        - method: GET
          path: /api/v1/projects/:id/gantt
          description: "Obtener datos para vista Gantt"
        - method: PUT
          path: /api/v1/projects/tasks/:id/reschedule
          description: "Reprogramar tarea"
        - method: POST
          path: /api/v1/projects/tasks/:id/dependencies
          description: "Crear dependencia entre tareas"
        - method: GET
          path: /api/v1/projects/:id/critical-path
          description: "Calcular ruta crítica"
      services:
        - name: "GanttService"
          file: "src/modules/projects/services/gantt.service.ts"
          methods:
            - getGanttData
            - rescheduleTask
            - createDependency
            - calculateCriticalPath
      controllers:
        - name: "GanttController"
          file: "src/modules/projects/controllers/gantt.controller.ts"
      dtos:
        - name: "RescheduleTaskDto"
          file: "src/modules/projects/dto/reschedule-task.dto.ts"
        - name: "CreateDependencyDto"
          file: "src/modules/projects/dto/create-dependency.dto.ts"
        - name: "GanttDataResponseDto"
          file: "src/modules/projects/dto/gantt-data-response.dto.ts"

    et_frontend:
      file: "especificaciones-tecnicas/frontend/mgn-011/ET-FRONTEND-MGN-011-005-vista-gantt-de-proyectos.md"
      routes:
        - path: "/projects/:id/gantt"
          component: "ProjectGanttPage"
      components:
        - name: "GanttChart"
          file: "src/widgets/gantt-chart/ui/GanttChart.tsx"
          type: widget
        - name: "GanttControls"
          file: "src/features/gantt-controls/ui/GanttControls.tsx"
          type: feature
        - name: "TaskDependencies"
          file: "src/entities/task/ui/TaskDependencies.tsx"
          type: entity
        - name: "GanttPage"
          file: "src/pages/projects/GanttPage.tsx"
          type: page
      api_client:
        - name: "ganttApi"
          file: "src/entities/gantt/api/gantt.api.ts"
          methods:
            - getGanttData
            - rescheduleTask
            - createDependency
            - getCriticalPath
      state_management:
        - name: "useGanttStore"
          file: "src/entities/gantt/model/gantt.store.ts"
          type: zustand

    database_tables:
      - schema: projects
        table: tasks
        file: "database-design/schemas/projects-schema-ddl.sql"
        operations:
          - SELECT
          - UPDATE
        indices:
          - idx_tasks_start_date
          - idx_tasks_end_date
        rls_policy: tenant_isolation_tasks
      - schema: projects
        table: task_dependencies
        file: "database-design/schemas/projects-schema-ddl.sql"
        operations:
          - SELECT
          - INSERT
          - DELETE
        indices:
          - idx_task_dependencies_task_id
          - idx_task_dependencies_depends_on_id
        rls_policy: tenant_isolation_task_dependencies

    tests:
      backend:
        unit_tests:
          - file: "src/modules/projects/services/gantt.service.spec.ts"
            test_cases:
              - "should generate Gantt data"
              - "should reschedule task with dependencies"
              - "should create task dependency"
              - "should calculate critical path"
              - "should validate circular dependencies"
        integration_tests:
          - file: "test/projects/gantt.controller.e2e-spec.ts"
            test_cases:
              - "GET /api/v1/projects/:id/gantt should return Gantt data"
              - "PUT /api/v1/projects/tasks/:id/reschedule should reschedule"
              - "POST /api/v1/projects/tasks/:id/dependencies should create dependency"
              - "GET /api/v1/projects/:id/critical-path should return path"
              - "should prevent circular dependencies"
              - "should enforce tenant isolation"
              - "should require authentication"
              - "should check permissions"
      frontend:
        component_tests:
          - file: "src/widgets/gantt-chart/ui/GanttChart.test.tsx"
            test_cases:
              - "should render Gantt chart"
              - "should drag to reschedule task"
              - "should show task dependencies"
          - file: "src/features/gantt-controls/ui/GanttControls.test.tsx"
            test_cases:
              - "should zoom in/out"
              - "should filter by resource"
              - "should highlight critical path"
        e2e_tests:
          - file: "e2e/projects/gantt.spec.ts"
            test_cases:
              - "should display Gantt chart"
              - "should reschedule task by dragging"
              - "should create task dependency"
              - "should enforce permissions"

    acceptance_criteria:
      - id: AC-001
        description: "Usuario puede visualizar proyecto en vista Gantt"
        status: Pending
        test_reference: "test/projects/gantt.controller.e2e-spec.ts:52"
      - id: AC-002
        description: "Tareas pueden reprogramarse con drag & drop"
        status: Pending
        test_reference: "src/widgets/gantt-chart/ui/GanttChart.test.tsx:88"
      - id: AC-003
        description: "Sistema calcula y muestra ruta crítica"
        status: Pending
        test_reference: "e2e/projects/gantt.spec.ts:125"

    business_rules:
      - id: RN-001
        description: "Dependencias no deben formar ciclos"
        implementation: "src/modules/projects/services/gantt.service.ts:validateNoCycles()"
        test_reference: "src/modules/projects/services/gantt.service.spec.ts:115"
      - id: RN-002
        description: "Reprogramar tarea ajusta automáticamente dependientes"
        implementation: "src/modules/projects/services/gantt.service.ts:rescheduleTask()"
        test_reference: "src/modules/projects/services/gantt.service.spec.ts:142"
      - id: RN-003
        description: "Ruta crítica identifica secuencia de tareas sin holgura"
        implementation: "src/modules/projects/services/gantt.service.ts:calculateCriticalPath()"
        test_reference: "src/modules/projects/services/gantt.service.spec.ts:168"

    dependencies:
      rf_dependencies:
        - RF-MGN-011-001
        - RF-MGN-011-002
      module_dependencies:
        - MGN-001
      external_dependencies:
        - name: "dhtmlx-gantt"
          version: "^8.0.0"

coverage:
  rf_to_et_backend: 100%
  rf_to_et_frontend: 100%
  rf_to_database: 100%
  rf_to_tests: 100%
  backend_tests: 100%
  frontend_tests: 100%

statistics:
  total_endpoints: 25
  total_components: 20
  total_tables: 5
  total_test_cases: 100
  estimated_duration_sprints: 2
