# Flujo de Negocio: Project (Proyectos) **Modulo:** project **Modelo Principal:** project.task **Aplica Workflow:** Si (basado en state + stage_id) --- ## 1. Estados de Tarea (state) | Estado | Nombre UI | Tipo | Descripcion | |--------|-----------|------|-------------| | 01_in_progress | In Progress | OPEN | Trabajo activo | | 02_changes_requested | Changes Requested | OPEN | Requiere modificaciones | | 03_approved | Approved | OPEN | Aprobada | | 04_waiting_normal | Waiting | OPEN | Bloqueada por dependencias | | 1_done | Done | CLOSED | Completada | | 1_canceled | Cancelled | CLOSED | Cancelada | --- ## 2. Diagrama de Estados ``` ┌──────────────────┐ │ CREAR TAREA │ │ state=in_progress│ └────────┬─────────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼ ┌──────────────────┐ ┌──────────────┐ ┌──────────────────┐ │ IN_PROGRESS │ │ WAITING │ │ APPROVED │ │ 01_in_progress │ │04_waiting_ │ │ 03_approved │ │ │ │ normal │ │ │ └────────┬─────────┘ └──────┬───────┘ └────────┬─────────┘ │ │ │ │ ┌──────────────┘ │ │ │ (dependencias resueltas) │ │ ▼ │ │ ┌─────────────────┐ │ │ │CHANGES_REQUESTED│ │ │ │02_changes_ │ │ │ │ requested │ │ │ └────────┬────────┘ │ │ │ │ └───────────┼───────────────────────────┘ │ ┌──────────┴──────────┐ │ │ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │ DONE │ │ CANCELED │ │ 1_done │ │ 1_canceled │ │ (is_closed=True)│ │ (is_closed=True)│ └──────────────────┘ └──────────────────┘ ``` --- ## 3. Etapas Kanban (stage_id) ``` ETAPAS POR PROYECTO: project.type_ids = [Stage1, Stage2, Stage3, ...] ASIGNACION: - Al crear tarea: stage_id = primera etapa del proyecto - Al mover en kanban: stage_id actualizado - stage.fold = True indica etapa final ETAPA PERSONAL: - Cada usuario puede tener diferente etapa - personal_stage_id computed por usuario - Sincronizado via project.task.stage.personal ``` --- ## 4. Flujo de Dependencias ``` TAREA A depende de TAREA B: A.depend_on_ids = [B] B.dependent_ids = [A] LOGICA _compute_state: ┌─────────────────────────────────────────────────┐ │ Para cada tarea: │ │ Si state en CLOSED_STATES: │ │ → mantener (ya cerrada) │ │ Si depend_on_ids tiene tareas no cerradas: │ │ → state = '04_waiting_normal' │ │ Si no: │ │ → mantener state actual │ └─────────────────────────────────────────────────┘ EFECTO: - Tarea A automaticamente en "Waiting" - Al cerrar B, A sale de "Waiting" ``` --- ## 5. Flujo de Subtareas ``` ESTRUCTURA: Tarea Padre ├── Subtarea 1 (child_ids) │ └── Subtarea 1.1 ├── Subtarea 2 └── Subtarea 3 HERENCIA: - Subtareas heredan project_id del padre - Subtareas pueden heredar milestone_id - Tags se copian del padre al crear CONTEO: subtask_count = len(child_ids) ``` --- ## 6. Flujo de Recurrencia ``` CONFIGURACION: ┌─────────────────────────────────────────────────┐ │ recurring_task = True │ │ repeat_interval = 1 │ │ repeat_unit = 'week' │ │ repeat_type = 'forever' | 'until' │ │ repeat_until = Date (si type='until') │ └─────────────────────────────────────────────────┘ AL CERRAR TAREA: 1. _inverse_state detecta cierre 2. Si recurring_task y recurrence_id: - Crea siguiente ocurrencia - Nueva tarea con fecha + repeat_interval 3. Nueva tarea en estado inicial ``` --- ## 7. Flujo de Milestones ``` ESTRUCTURA: project.milestone ├── deadline: Fecha objetivo ├── is_reached: Marcado como alcanzado └── task_ids: Tareas vinculadas ASIGNACION: - Tarea.milestone_id = hito seleccionado - Subtareas heredan milestone del padre - Validacion: milestone debe estar en mismo proyecto TRACKING: - task_count: Total tareas en hito - done_task_count: Tareas cerradas - Progreso = done_task_count / task_count ``` --- ## 8. Metodos de Transicion ### _compute_state() ```python @api.depends('stage_id', 'depend_on_ids.state') def _compute_state(self): for task in self: # No cambiar si ya cerrada if task.state in CLOSED_STATES: continue # Verificar dependencias bloqueadas has_blocking = any( dep.state not in CLOSED_STATES for dep in task.depend_on_ids ) if has_blocking: task.state = '04_waiting_normal' ``` ### _inverse_state() ```python def _inverse_state(self): # Maneja recurrencia al cerrar for task in self: if task.state in CLOSED_STATES and task.recurring_task: task._create_next_recurrence() ``` ### update_date_end(stage_id) ```python def update_date_end(self, stage_id): stage = self.env['project.task.type'].browse(stage_id) if stage.fold: # Etapa final self.write({'date_end': fields.Datetime.now()}) else: self.write({'date_end': False}) ``` ### stage_find(section_id, domain, order) ```python def stage_find(self, section_id, domain=[], order='sequence, id'): # Buscar etapa valida para el proyecto # Considera etapas del proyecto o por defecto return stage_id ``` --- ## 9. Reglas de Negocio | ID | Regla | Validacion | Mensaje | |----|-------|------------|---------| | R1 | Proyecto requerido | project_id presente | Seleccione proyecto | | R2 | Milestone mismo proyecto | milestone.project_id = project_id | Milestone invalido | | R3 | No auto-dependencia | task not in depend_on_ids | No puede depender de si misma | | R4 | No ciclo dependencias | Validar DAG | Dependencia circular | --- ## 10. Acciones Automaticas | Trigger | Accion | Condicion | |---------|--------|-----------| | stage_id change | update_date_end | Si stage.fold = True | | stage_id change | date_last_stage_update | Siempre | | user_ids change | date_assign | Primera asignacion | | Cierre tarea recurrente | Crear siguiente | Si recurring_task | | depend_on_ids change | Recalcular state | Siempre | --- ## 11. Permisos por Portal ### Campos Leibles ```python PROJECT_TASK_READABLE_FIELDS = { 'id', 'active', 'priority', 'project_id', 'user_ids', 'date_deadline', 'date_assign', 'subtask_count', 'milestone_id', 'stage_id', 'tag_ids', 'partner_id', 'display_name', 'recurring_task', ... } ``` ### Campos Escribibles ```python PROJECT_TASK_WRITABLE_FIELDS = { 'name', 'description', 'partner_id', 'date_deadline', 'tag_ids', 'sequence', 'stage_id', 'child_ids', 'parent_id', 'priority', 'state', 'is_closed', ... } ``` --- ## 12. Flujo Completo de Tarea ``` 1. CREAR TAREA └─ state = '01_in_progress' └─ stage_id = primera etapa proyecto └─ date_create = ahora 2. ASIGNACION └─ user_ids asignados └─ date_assign = ahora (primera vez) 3. TRABAJO └─ Cambios de stage_id (kanban) └─ date_last_stage_update actualizado └─ Si tiene dependencias → puede ir a 'waiting' 4. REVISION (opcional) └─ state = '02_changes_requested' └─ state = '03_approved' 5. CIERRE └─ state = '1_done' o '1_canceled' └─ is_closed = True └─ date_end = ahora (si stage.fold) └─ Si recurrente → crea siguiente 6. RECURRENCIA (si aplica) └─ Nueva tarea creada └─ Fechas ajustadas segun interval └─ state = inicial ``` --- **Referencias:** - project_task.py: _compute_state, _inverse_state, update_date_end - project_task_type.py: fold, sequence - project_milestone.py: is_reached, task_count