"""Consolidate 3 finance templates into 1 Finance & Accounting Manager Revision ID: 011 Revises: 010 Create Date: 2026-03-26 SMBs don't need separate Financial Manager, Controller, and Accountant templates. Consolidates into a single versatile Finance & Accounting Manager that covers invoicing, budgets, reporting, and compliance. """ from __future__ import annotations import json from typing import Sequence, Union from alembic import op revision: str = "011" down_revision: Union[str, None] = "010" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None NEW_NAME = "Finance & Accounting Manager" NEW_ROLE = "Finance & Accounting Manager" NEW_DESCRIPTION = ( "A versatile finance professional that handles invoicing, accounts payable/receivable, " "expense tracking, budget monitoring, financial reporting, and cash flow analysis. " "Keeps the books accurate, flags budget overruns early, and provides clear financial " "summaries for business owners. Escalates unusual transactions, large expenses, and " "compliance questions to leadership." ) NEW_PERSONA = ( "You are meticulous, trustworthy, and proactive about financial health. You handle " "the full spectrum of SMB finance — from processing invoices and reconciling expenses " "to preparing monthly reports and monitoring cash flow. You communicate financial " "information in plain language that non-finance stakeholders can understand. You flag " "anomalies and budget risks early rather than waiting for month-end surprises. You " "escalate decisions involving significant expenditures, tax matters, or regulatory " "compliance to the business owner." ) NEW_TOOLS = json.dumps(["knowledge_base_search"]) NEW_ESCALATION = json.dumps([ {"condition": "transaction_amount > 5000", "action": "handoff_human"}, {"condition": "tax_or_compliance_question", "action": "handoff_human"}, {"condition": "budget_overrun AND percentage > 15", "action": "handoff_human"}, ]) NEW_TRANSLATIONS = json.dumps({ "es": { "name": "Gerente de Finanzas y Contabilidad", "description": ( "Un profesional financiero versátil que gestiona facturación, cuentas por pagar y " "cobrar, seguimiento de gastos, monitoreo de presupuesto, informes financieros y " "análisis de flujo de caja. Mantiene los libros precisos, señala desviaciones " "presupuestarias tempranamente y proporciona resúmenes financieros claros para los " "propietarios del negocio. Escala transacciones inusuales, gastos importantes y " "consultas de cumplimiento al liderazgo." ), "persona": ( "Eres meticuloso, confiable y proactivo con la salud financiera. Manejas todo el " "espectro de finanzas para PyMEs — desde procesar facturas y conciliar gastos hasta " "preparar informes mensuales y monitorear el flujo de caja. Comunicas la información " "financiera en un lenguaje claro que los interesados no financieros pueden entender. " "Señalas anomalías y riesgos presupuestarios tempranamente en lugar de esperar a las " "sorpresas de fin de mes. Escalas decisiones que involucran gastos significativos, " "asuntos fiscales o cumplimiento regulatorio al propietario del negocio." ), }, "pt": { "name": "Gerente de Finanças e Contabilidade", "description": ( "Um profissional financeiro versátil que gerencia faturamento, contas a pagar e " "receber, acompanhamento de despesas, monitoramento de orçamento, relatórios " "financeiros e análise de fluxo de caixa. Mantém os registros precisos, sinaliza " "desvios orçamentários precocemente e fornece resumos financeiros claros para os " "proprietários do negócio. Escala transações incomuns, despesas significativas e " "questões de conformidade para a liderança." ), "persona": ( "Você é meticuloso, confiável e proativo com a saúde financeira. Você lida com " "todo o espectro de finanças para PMEs — desde processar faturas e conciliar " "despesas até preparar relatórios mensais e monitorar o fluxo de caixa. Você " "comunica informações financeiras em linguagem clara que stakeholders não " "financeiros conseguem entender. Você sinaliza anomalias e riscos orçamentários " "precocemente em vez de esperar surpresas no fechamento do mês. Você escala " "decisões que envolvem gastos significativos, questões fiscais ou conformidade " "regulatória para o proprietário do negócio." ), }, }) def upgrade() -> None: # Update the Financial Manager template to become the consolidated one op.execute(f""" UPDATE agent_templates SET name = '{NEW_NAME}', role = '{NEW_ROLE}', description = '{NEW_DESCRIPTION.replace("'", "''")}', persona = '{NEW_PERSONA.replace("'", "''")}', tool_assignments = '{NEW_TOOLS}'::jsonb, escalation_rules = '{NEW_ESCALATION}'::jsonb, sort_order = 50, translations = '{NEW_TRANSLATIONS}'::jsonb WHERE name = 'Financial Manager' """) # Remove Controller and Accountant op.execute("DELETE FROM agent_templates WHERE name = 'Controller'") op.execute("DELETE FROM agent_templates WHERE name = 'Accountant'") def downgrade() -> None: # Restore the original Financial Manager op.execute(""" UPDATE agent_templates SET name = 'Financial Manager', role = 'Financial Planning and Analysis Manager', sort_order = 50 WHERE name = 'Finance & Accounting Manager' """) # Re-insert Controller and Accountant (minimal — full restore would need original data) op.execute(""" INSERT INTO agent_templates (id, name, role, description, category, persona, system_prompt, model_preference, tool_assignments, escalation_rules, is_active, sort_order, translations) VALUES (gen_random_uuid(), 'Controller', 'Financial Controller', 'Financial controller template', 'finance', '', '', 'balanced', '[]'::jsonb, '[]'::jsonb, true, 60, '{}'::jsonb) """) op.execute(""" INSERT INTO agent_templates (id, name, role, description, category, persona, system_prompt, model_preference, tool_assignments, escalation_rules, is_active, sort_order, translations) VALUES (gen_random_uuid(), 'Accountant', 'Staff Accountant', 'Staff accountant template', 'finance', '', '', 'balanced', '[]'::jsonb, '[]'::jsonb, true, 70, '{}'::jsonb) """)