--- name: auto-expense description: Criação automática de despesas a partir de facturas detectadas no IMAP e tickets. Extrai dados, verifica duplicados por reference_no e cria despesas no Desk CRM com PDF anexo. disable-model-invocation: true --- # /auto-expense v1.1 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 (OBRIGATORIO — guardar para dedup) - Data da factura ``` ### Passo 3: Verificar duplicados (OBRIGATORIO — 3 camadas) > **CRITICO: Este passo NUNCA pode ser saltado. Se saltado, causa duplicacao massiva de despesas.** ``` Camada 0 — Referencia de factura (PRIMARIA, mais fiavel): get_expenses(search: "") Para cada resultado: comparar campo reference_no Se alguma despesa tem reference_no IGUAL → DUPLICADO CONFIRMADO → NAO criar, registar como duplicado com ID existente Camada 1 — Fornecedor + Valor + Data: get_expenses(search: "") Filtrar: mesmo valor (±0.05) + mesma data (±3 dias) Se match → NAO criar, registar como duplicado Camada 2 — Expense name pattern: get_expenses(search: " - ") Se match exacto no expense_name → NAO criar, registar como duplicado REGRA: Se QUALQUER camada detecta duplicado → PARAR imediatamente. Nunca criar despesa sem passar as 3 camadas com sucesso. Registar cada duplicado detectado no output JSON (campo "duplicados"). ``` ### Passo 4: Criar despesa ``` APENAS se Passo 3 passou sem detectar duplicado: mcp__desk-crm-v3__create_expense({ category: [cat_id da tabela], amount: [valor], date: [data factura YYYY-MM-DD], expense_name: "[Fornecedor] - [Referencia]", reference_no: "[numero factura/referencia]", note: "Auto-criado via /auto-expense", currency: [2=USD ou 3=EUR], tax: [0 ou 1], send_invoice_to_customer: 0 }) OBRIGATORIO: campo reference_no DEVE ser preenchido com o numero de factura extraido. Este campo e a chave primaria de deduplicacao. ``` ### Passo 5: 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 6: 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 7: 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": [ {"fornecedor": "MEO", "referencia": "FT A/861215955", "existente_id": 1175, "camada": 0} ], "flagged": [ {"fornecedor": "Desconhecido", "nota": "TOConline - emitente desconhecido: XPTO LDA"} ], "erros": [], "total_processadas": 1, "total_duplicados": 0 } ``` --- ## 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") — CHAVE DE DEDUPLICACAO ``` --- ## Output Standalone ```markdown ## Auto-Despesas - DD-MM-YYYY ### Despesas Criadas (X) | # Desk | Fornecedor | Valor | Moeda | Ref | PDF | |--------|-----------|-------|-------|-----|-----| ### Duplicados Detectados (Y) | Fornecedor | Ref | ID Existente | Camada | |-----------|-----|-------------|--------| ### 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 (3 camadas obrigatorias) - NUNCA omitir send_invoice_to_customer=0 - NUNCA omitir reference_no ao criar despesa (chave primaria de dedup) - NUNCA saltar a Camada 0 (referencia de factura) — e a mais fiavel - SEMPRE ler o email/ticket HTML para extrair valor real (nunca assumir) - SEMPRE incluir reference_no quando disponivel - SEMPRE logar duplicados detectados no output JSON com camada e ID existente --- *Skill v1.1.0 | 30-03-2026 | Descomplicar | Fix: dedup por reference_no (DES-137)* --- ## Healing Log Registo de erros conhecidos e como evitá-los. Lido automaticamente antes de executar. ```jsonl {"date":"","issue":"","fix":"","source":"user|auto"} ``` *Adicionar nova linha após cada erro corrigido.*