--- name: auto-expense description: > Criacao automatica de despesas a partir de facturas detectadas no IMAP e tickets. Le ficheiros JSON de /imap-triage e /ticket-triage, extrai dados das facturas, cria despesas no Desk CRM com PDF. Use when "auto despesa", "processar facturas", "auto-expense", "despesas automaticas". author: Descomplicar® Crescimento Digital version: 1.0.0 quality_score: 85 user_invocable: true category: finance tags: [expense, auto, invoices, imap, tickets, pdf, desk-crm] desk_task: 1710 desk_project: 65 allowed-tools: Read, Write, mcp__desk-crm-v3, mcp__imap, mcp__ssh-unified mcps: desk-crm-v3, imap, ssh-unified dependencies: mcps: [desk-crm-v3, imap, ssh-unified] skills: [imap-triage, ticket-triage] files: - /media/ealmeida/Dados/Hub/06-Operacoes/Documentacao/fornecedores-recorrentes.md triggers: - "User asks to process invoices as expenses" - "User mentions 'auto despesa', 'processar facturas'" - "Invoked by /today orchestrator after /imap-triage and /ticket-triage" --- # /auto-expense v1.0 Cria despesas automaticamente a partir de facturas detectadas pelo IMAP e tickets. --- ## Protocolo ### Passo 1: Carregar inputs ``` 1. Ler ficheiro fornecedores: Read: /media/ealmeida/Dados/Hub/06-Operacoes/Documentacao/fornecedores-recorrentes.md 2. Ler facturas IMAP (se existir): Read: ~/.claude-work/today-imap-{date}.json → campo "facturas" 3. Ler facturas tickets (se existir): Read: ~/.claude-work/today-tickets-{date}.json → campo "facturas" 4. Se nenhum ficheiro existe E invocado standalone: → Perguntar ao utilizador: "processar IMAP, tickets ou ambos?" → Se IMAP: executar /imap-triage primeiro → Se tickets: executar /ticket-triage primeiro ``` ### Passo 2: Para cada factura, processar ``` Para cada factura na lista: 1. DETECTAR FORNECEDOR: a. Fornecedor directo: dominio remetente na tabela → categoria, tax e moeda ja conhecidos b. Plataforma multi-fornecedor (toconline, stripe, paypal, fastspring, payproglobal): → LER email completo → EXTRAIR emitente real → Procurar emitente na tabela "Emitentes Conhecidos por Plataforma" → SE desconhecido: registar como priority_flagged, PARAR este email 2. LER EMAIL/TICKET: - IMAP: imap_read_email(account, uid) → HTML + anexos - Ticket: mcp__desk-crm-v3__get_ticket(ticket_id) → HTML 3. EXTRAIR DO HTML: - Valor (padroes: $XX.XX, XX,XX EUR, USD XX.XX, Total: XX.XX) - Referencia/Invoice number - Data da factura 4. VERIFICAR DUPLICADO (2 camadas): Camada 1 - Desk CRM: Pesquisar: mesmo fornecedor + mesmo valor (±0.05) + mesma data (±3 dias) Se match → NAO criar, registar como duplicado 5. CRIAR DESPESA: mcp__desk-crm-v3__create_expense({ category: [cat_id da tabela], amount: [valor], date: [data factura YYYY-MM-DD], expense_name: "[Fornecedor] - [Referencia]", note: "Auto-criado via /auto-expense", currency: [2=USD ou 3=EUR], tax: [0 ou 1], send_invoice_to_customer: 0 }) ``` ### Passo 3: PDF (se existir anexo) ``` a. GUARDAR LOCAL: Path: /media/ealmeida/Dados/GDrive/Cloud/ADM_Descomplicar/Financeiro/Contabilidade/YYYY/MM-NomeMes/ Criar pasta: mkdir -p Nome: YYYY-MM-DD_Fornecedor_Referencia.pdf Meses PT: 01-Janeiro, 02-Fevereiro, 03-Marco, 04-Abril, 05-Maio, 06-Junho, 07-Julho, 08-Agosto, 09-Setembro, 10-Outubro, 11-Novembro, 12-Dezembro b. UPLOAD ao Desk servidor: mcp__ssh-unified__sftp_upload(server="desk", local_path, remote_path="/tmp/") mcp__ssh-unified__ssh_execute(server="desk", command=" mkdir -p /home/ealmeida/desk24/uploads/expenses/{expense_id}/ cp /tmp/{filename} /home/ealmeida/desk24/uploads/expenses/{expense_id}/ chown -R ealmeida:ealmeida /home/ealmeida/desk24/uploads/expenses/{expense_id}/ rm /tmp/{filename} ") c. REGISTAR no Desk BD: mcp__ssh-unified__ssh_execute(server="desk", command=" mysql -u ealmeida -p'9qPRdCGGqM4o' ealmeida_desk24 -e \" INSERT INTO tblfiles (rel_id, rel_type, file_name, filetype, attachment_key, staffid, dateadded) VALUES ({expense_id}, 'expense', '{filename}', 'application/pdf', MD5(RAND()), 25, NOW()); \" ") d. LIMPAR temporarios ``` ### Passo 4: Actualizar CSV ``` CSV Path: /media/ealmeida/Dados/GDrive/Cloud/ADM_Descomplicar/Financeiro/Contabilidade/YYYY/MAPA-DESPESAS-YYYY.csv Formato linha: id_desk;data;categoria;fornecedor;descricao;valor;SIM;ficheiro;email;Auto /auto-expense ``` ### Passo 5: Escrever output JSON ``` Escrever em ~/.claude-work/today-expenses-{date}.json: { "despesas_criadas": [ {"id": 1180, "fornecedor": "MEO", "valor": 76.26, "moeda": "EUR", "referencia": "FT A/861215955"} ], "duplicados": 0, "flagged": [ {"fornecedor": "Desconhecido", "nota": "TOConline - emitente desconhecido: XPTO LDA"} ], "erros": [], "total_processadas": 1 } ``` --- ## Plataformas Multi-Fornecedor - Padroes de Extracao > Ver tabela completa em: Hub/06-Operacoes/Documentacao/fornecedores-recorrentes.md | Plataforma | Padrao no Subject/HTML | |-----------|----------------------| | TOConline | "Emitido por:", "Emitente:" no HTML | | Stripe | "Receipt from [Empresa]" ou "Your receipt from [Empresa]" no subject | | PayPal | "You paid [Empresa]" no subject | | FastSpring | "Order from [Empresa]" no subject/corpo | | PayPro Global | Nome produto/empresa no corpo | --- ## Campos Criticos Desk CRM ``` currency = 3 (EUR) → Fornecedores EUR currency = 2 (USD) → Fornecedores USD (manter valor original, NAO converter) currency = 1 → NAO EXISTE - causa despesas invisiveis tax = 1 → Fornecedores PT (MEO, Moloni, PTisp, Staples) tax = 0 → Fornecedores estrangeiros send_invoice_to_customer = 0 → OBRIGATORIO (sem default na BD) reference_no → coluna correcta (NAO "reference") ``` --- ## Output Standalone ```markdown ## Auto-Despesas - DD-MM-YYYY ### Despesas Criadas (X) | # Desk | Fornecedor | Valor | Moeda | Ref | PDF | |--------|-----------|-------|-------|-----|-----| ### Duplicados Detectados (Y) - [Fornecedor] [Valor] - ja existe como #ID ### Pendentes Revisao (Z) - [Plataforma] - emitente desconhecido: [nome] ``` --- ## Anti-Patterns - NUNCA usar currency=1 (nao existe) - NUNCA converter USD para EUR (manter original com currency=2) - NUNCA criar despesa sem verificar duplicado primeiro - NUNCA omitir send_invoice_to_customer=0 - SEMPRE ler o email/ticket HTML para extrair valor real (nunca assumir) - SEMPRE incluir reference_no quando disponivel --- *Skill v1.0.0 | 04-03-2026 | Descomplicar®*