feat(sprint-3): biblioteca, recursos TO-BE, ROI mejorado e identidad de marca
Sprint 3 completo — 7 etapas: - Etapa 1-2: biblioteca de procesos con agrupación por cliente (Dexie v4, LibraryPage, library-store, groupId/tags en Process) - Etapa 3: modal de configuración global por proceso (horizonte, frecuencia, inversión, moneda) con validación y persistencia - Etapa 4: panel de recursos rediseñado con soporte de unidades y minutos de utilización (utilizationMinutes + units) - Etapa 5: recursos en escenario automatizado — motor de simulación, UI de edición en ActivityPanel, comparación AS-IS/TO-BE en reporte - Etapa 6: PDF recursos automatizados, automatedAssignedResources requerido, 561 tests pasando - Etapa 7: identidad de marca — AppHeader gradiente naranja/magenta con logo InQuality en 5 páginas, favicon con logo real, logo/marca navegan a home Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -227,7 +227,7 @@ describe('MethodologyFooter', () => {
|
||||
id: 'p1', name: 'Proceso Test', clientName: '',
|
||||
bpmnXml: '<def/>', currency: 'USD',
|
||||
overheadPercentage: 0.2, annualFrequency: 1000, analysisHorizonYears: 3, automationInvestment: 0,
|
||||
createdAt: 0, updatedAt: 0,
|
||||
createdAt: 0, updatedAt: 0, groupId: null, tags: [],
|
||||
}
|
||||
expect(() => render(<MethodologyFooter process={proc} />)).not.toThrow()
|
||||
})
|
||||
@@ -237,7 +237,7 @@ describe('MethodologyFooter', () => {
|
||||
id: 'p1', name: 'Proc', clientName: '',
|
||||
bpmnXml: '', currency: 'USD',
|
||||
overheadPercentage: 0.25, annualFrequency: 1000, analysisHorizonYears: 3, automationInvestment: 0,
|
||||
createdAt: 0, updatedAt: 0,
|
||||
createdAt: 0, updatedAt: 0, groupId: null, tags: [],
|
||||
}
|
||||
render(<MethodologyFooter process={proc} />)
|
||||
const text = document.body.textContent ?? ''
|
||||
@@ -249,7 +249,7 @@ describe('MethodologyFooter', () => {
|
||||
id: 'p1', name: 'Proc', clientName: '',
|
||||
bpmnXml: '', currency: 'USD',
|
||||
overheadPercentage: 0.2, annualFrequency: 1000, analysisHorizonYears: 3, automationInvestment: 0,
|
||||
createdAt: 0, updatedAt: 0,
|
||||
createdAt: 0, updatedAt: 0, groupId: null, tags: [],
|
||||
}
|
||||
render(<MethodologyFooter process={proc} />)
|
||||
const text = document.body.textContent ?? ''
|
||||
@@ -334,6 +334,8 @@ describe('ReportPage — con datos completos', () => {
|
||||
automationInvestment: 0,
|
||||
createdAt: Date.now() - 1000 * 60 * 30,
|
||||
updatedAt: Date.now() - 1000 * 60 * 30,
|
||||
groupId: null,
|
||||
tags: [],
|
||||
}
|
||||
|
||||
const mockSimulation = {
|
||||
|
||||
@@ -31,7 +31,7 @@ function buildSimInput(xml: string, directCost: number, overhead: number, curren
|
||||
directCostFixed: directCost,
|
||||
executionTimeMinutes: 30,
|
||||
assignedResources: [],
|
||||
automatable: false, automatedCostFixed: 0, automatedTimeMinutes: 0,
|
||||
automatable: false, automatedCostFixed: 0, automatedTimeMinutes: 0, automatedAssignedResources: [],
|
||||
}])
|
||||
)
|
||||
|
||||
|
||||
@@ -157,9 +157,10 @@ describe('RoiKpiBar', () => {
|
||||
expect(screen.getByText(/Inmediato/i)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('ROI Infinity (inversión cero) → muestra "∞%"', () => {
|
||||
it('ROI Infinity (inversión cero) → muestra "—" con texto accionable', () => {
|
||||
render(<RoiKpiBar roi={roiZeroInvestment} currency="USD" horizonYears={3} />)
|
||||
expect(screen.getByText('∞%')).toBeInTheDocument()
|
||||
expect(screen.getByText('—')).toBeInTheDocument()
|
||||
expect(screen.getByText(/Configurá la inversión/i)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('ahorro negativo: "breaksEvenInHorizon = false" → subtexto fuera del horizonte', () => {
|
||||
@@ -311,6 +312,7 @@ const makeActivityDomain = (id: string, name: string, automatable: boolean, zero
|
||||
automatable,
|
||||
automatedCostFixed: zeroCosts ? 0 : 50,
|
||||
automatedTimeMinutes: zeroCosts ? 0 : 10,
|
||||
automatedAssignedResources: [],
|
||||
})
|
||||
|
||||
describe('TransparencySection', () => {
|
||||
@@ -586,6 +588,7 @@ const mockProcessBase = {
|
||||
currency: 'USD', overheadPercentage: 0.2,
|
||||
annualFrequency: 1200, analysisHorizonYears: 3, automationInvestment: 50_000,
|
||||
createdAt: Date.now() - 3600_000, updatedAt: Date.now() - 3600_000,
|
||||
groupId: null, tags: [],
|
||||
}
|
||||
|
||||
const mockSimulationBase = {
|
||||
@@ -598,6 +601,7 @@ const automtableActivity: Activity = {
|
||||
id: 'act-1', processId: 'test-proc-id', bpmnElementId: 'bpmn_a1', name: 'Recibir solicitud',
|
||||
type: 'task', directCostFixed: 500, executionTimeMinutes: 60, assignedResources: [],
|
||||
automatable: true, automatedCostFixed: 50, automatedTimeMinutes: 5,
|
||||
automatedAssignedResources: [],
|
||||
}
|
||||
|
||||
const nonAutomatableActivity: Activity = {
|
||||
|
||||
Reference in New Issue
Block a user