#!/usr/bin/env python3 """ Enkel Aamos Ledger Client Använder direkt SQL via psycopg2 istället för API:et """ import psycopg2 from datetime import datetime, timezone from typing import List, Dict, Optional DB_CONFIG = { "host": "localhost", "database": "aamos_ledger", "user": "postgres", "password": "quixzo…2026" } class SimpleAamosClient: """Enkel klient som använder direkt SQL""" def __init__(self): self.conn = None def connect(self): """Anslut till databasen""" self.conn = psycopg2.connect(**DB_CONFIG) return self def list_accounts(self) -> List[Dict]: """Lista alla konton""" with self.conn.cursor() as cur: cur.execute(""" SELECT id, code, name, account_type, created_at FROM accounts ORDER BY code """) columns = [desc[0] for desc in cur.description] return [dict(zip(columns, row)) for row in cur.fetchall()] def get_account(self, code: str) -> Optional[Dict]: """Hämta konto efter kod""" with self.conn.cursor() as cur: cur.execute(""" SELECT id, code, name, account_type, created_at FROM accounts WHERE code = %s """, (code,)) row = cur.fetchone() if row: columns = [desc[0] for desc in cur.description] return dict(zip(columns, row)) return None def create_journal_entry(self, entry_number: str, description: str, entry_date: str, lines: List[Dict]) -> Optional[str]: """Skapa verifikat med rader""" try: with self.conn.cursor() as cur: # Skapa verifikat cur.execute(""" INSERT INTO journal_entries (entry_number, description, entry_date, status) VALUES (%s, %s, %s, 'draft') RETURNING id """, (entry_number, description, entry_date)) entry_id = cur.fetchone()[0] # Skapa rader for line in lines: cur.execute(""" INSERT INTO journal_lines (journal_entry_id, account_id, debit, credit, description) VALUES (%s, %s, %s, %s, %s) """, ( entry_id, line['account_id'], line.get('debit', 0), line.get('credit', 0), line.get('description', '') )) self.conn.commit() return entry_id except Exception as e: self.conn.rollback() print(f"Fel vid skapande av verifikat: {e}") return None def get_trial_balance(self) -> List[Dict]: """Hämta saldoöversikt""" with self.conn.cursor() as cur: cur.execute(""" SELECT a.code, a.name, a.account_type, COALESCE(SUM(jl.debit), 0) as total_debit, COALESCE(SUM(jl.credit), 0) as total_credit, COALESCE(SUM(jl.debit), 0) - COALESCE(SUM(jl.credit), 0) as balance FROM accounts a LEFT JOIN journal_lines jl ON a.id = jl.account_id LEFT JOIN journal_entries je ON jl.journal_entry_id = je.id WHERE je.status = 'posted' OR je.status IS NULL GROUP BY a.id, a.code, a.name, a.account_type ORDER BY a.code """) columns = [desc[0] for desc in cur.description] return [dict(zip(columns, row)) for row in cur.fetchall()] def close(self): """Stäng anslutningen""" if self.conn: self.conn.close() def test_simple_client(): """Testa den enkla klienten""" client = SimpleAamosClient().connect() print("=== AAMOS LEDGER (Direkt SQL) ===\n") # Lista konton accounts = client.list_accounts() print(f"Konton ({len(accounts)}):") for acc in accounts[:5]: print(f" {acc['code']}: {acc['name']} ({acc['account_type']})") # Hämta saldoöversikt print("\nSaldoöversikt:") tb = client.get_trial_balance() for row in tb[:5]: print(f" {row['code']}: {row['name']} | Debet: {row['total_debit']} | Kredit: {row['total_credit']} | Saldo: {row['balance']}") client.close() print("\n✅ Test klart!") if __name__ == "__main__": test_simple_client()