felhasználói felületre pü
This commit is contained in:
155
backend/scripts/seed_financial_ledger.py
Normal file
155
backend/scripts/seed_financial_ledger.py
Normal file
@@ -0,0 +1,155 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Seed script: Populate audit.financial_ledger with 20 dummy records.
|
||||
Uses psycopg2 (sync) to bypass asyncpg prepared statement enum validation issues.
|
||||
"""
|
||||
import uuid
|
||||
import random
|
||||
import os
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
import psycopg2
|
||||
|
||||
TRANSACTION_TYPES = [
|
||||
"SUBSCRIPTION", "COMMISSION", "REFUND", "MANUAL_ADJUSTMENT",
|
||||
"PURCHASE", "WITHDRAWAL", "BONUS", "FEE", "REWARD",
|
||||
]
|
||||
|
||||
DB_ENTRY_TYPES = ["CREDIT", "DEBIT"]
|
||||
DB_WALLET_TYPES = ["EARNED", "PURCHASED", "SERVICE_COINS", "VOUCHER"]
|
||||
DB_STATUSES = ["PENDING", "SUCCESS", "FAILED", "REFUNDED"]
|
||||
|
||||
TEST_USER_IDS = [1, 2, 28, 29, 55, 75, 79, 85, 86, 88, 100, 102, 103, 104, 105, 106]
|
||||
|
||||
NOW = datetime.now(timezone.utc)
|
||||
|
||||
|
||||
def get_dsn_params():
|
||||
"""Extract connection parameters from DATABASE_URL."""
|
||||
db_url = os.environ.get("DATABASE_URL", "postgresql+asyncpg://service_finder_app:AppSafePass_2026@shared-postgres:5432/service_finder")
|
||||
db_url = db_url.replace("postgresql+asyncpg://", "postgresql://")
|
||||
# Parse URL
|
||||
parts = db_url.replace("postgresql://", "").split("@")
|
||||
user_pass = parts[0].split(":")
|
||||
host_db = parts[1].split("/")
|
||||
host_port = host_db[0].split(":")
|
||||
return {
|
||||
"user": user_pass[0],
|
||||
"password": user_pass[1],
|
||||
"host": host_port[0],
|
||||
"port": int(host_port[1]) if len(host_port) > 1 else 5432,
|
||||
"dbname": host_db[1].split("?")[0],
|
||||
}
|
||||
|
||||
|
||||
def seed():
|
||||
params = get_dsn_params()
|
||||
conn = psycopg2.connect(**params)
|
||||
conn.autocommit = False
|
||||
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
# Count existing
|
||||
cur.execute("SELECT COUNT(*) FROM audit.financial_ledger")
|
||||
print(f"Existing records: {cur.fetchone()[0]}")
|
||||
|
||||
# Get person_ids
|
||||
person_map = {}
|
||||
for uid in TEST_USER_IDS:
|
||||
cur.execute("SELECT person_id FROM identity.users WHERE id = %s", (uid,))
|
||||
pid = cur.fetchone()
|
||||
if pid and pid[0]:
|
||||
person_map[uid] = pid[0]
|
||||
|
||||
if not person_map:
|
||||
print("No users with person_id found!")
|
||||
return
|
||||
|
||||
print(f"Users with person records: {list(person_map.keys())}")
|
||||
|
||||
inserted = 0
|
||||
for i in range(20):
|
||||
uid = random.choice(list(person_map.keys()))
|
||||
pid = person_map[uid]
|
||||
entry_t = random.choice(DB_ENTRY_TYPES)
|
||||
wallet_t = random.choice(DB_WALLET_TYPES)
|
||||
stat = random.choice(DB_STATUSES)
|
||||
txn_t = random.choice(TRANSACTION_TYPES)
|
||||
cur_r = random.choice(["HUF", "EUR", "USD", "GBP"])
|
||||
amt = round(random.uniform(5.0, 5000.0), 2)
|
||||
days_ago = random.randint(0, 30)
|
||||
created_ts = NOW - timedelta(
|
||||
days=random.randint(0, days_ago),
|
||||
hours=random.randint(0, 23),
|
||||
minutes=random.randint(0, 59),
|
||||
)
|
||||
ref = "TXN-" + uuid.uuid4().hex[:8].upper()
|
||||
desc = txn_t.lower().replace("_", " ").title() + f" for user {uid}"
|
||||
net_amt = round(amt / 1.27, 2) if random.random() > 0.3 else None
|
||||
tax_amt = round(amt - net_amt, 2) if net_amt else None
|
||||
balance = round(random.uniform(100, 50000), 2)
|
||||
inv_stat = "PAID" if stat == "completed" else stat.upper()
|
||||
txn_id = str(uuid.uuid4())
|
||||
|
||||
# psycopg2 handles text → enum cast correctly with simple execute
|
||||
cur.execute(
|
||||
"""
|
||||
INSERT INTO audit.financial_ledger
|
||||
(user_id, person_id, amount, currency, transaction_type, details,
|
||||
created_at, entry_type, balance_after, wallet_type, status,
|
||||
transaction_id, net_amount, tax_amount, gross_amount, invoice_status)
|
||||
VALUES (
|
||||
%s, %s, %s, %s, %s,
|
||||
%s::jsonb,
|
||||
%s::timestamptz,
|
||||
%s::audit.ledger_entry_type,
|
||||
%s,
|
||||
%s::audit.wallet_type,
|
||||
%s::audit.ledger_status,
|
||||
%s::uuid,
|
||||
%s, %s, %s, %s
|
||||
)
|
||||
""",
|
||||
(
|
||||
uid, pid, amt, cur_r, txn_t,
|
||||
f'{{"description": "{desc}", "reference": "{ref}"}}',
|
||||
created_ts.isoformat(),
|
||||
entry_t, balance, wallet_t, stat, txn_id,
|
||||
net_amt, tax_amt, amt, inv_stat,
|
||||
),
|
||||
)
|
||||
inserted += 1
|
||||
|
||||
conn.commit()
|
||||
print(f"✅ Inserted {inserted} records successfully!")
|
||||
|
||||
cur.execute("SELECT COUNT(*) FROM audit.financial_ledger")
|
||||
print(f"Total records now: {cur.fetchone()[0]}")
|
||||
|
||||
cur.execute("""
|
||||
SELECT
|
||||
fl.entry_type::text,
|
||||
fl.wallet_type::text,
|
||||
fl.status::text,
|
||||
COUNT(*)::int,
|
||||
ROUND(AVG(fl.amount)::numeric, 2),
|
||||
u.email
|
||||
FROM audit.financial_ledger fl
|
||||
LEFT JOIN identity.users u ON u.id = fl.user_id
|
||||
GROUP BY fl.entry_type, fl.wallet_type, fl.status, u.email
|
||||
ORDER BY fl.entry_type, fl.wallet_type
|
||||
""")
|
||||
rows = cur.fetchall()
|
||||
total_sum = sum(r[3] for r in rows) if rows else 0
|
||||
print(f"\n📊 Summary (total {total_sum} records):")
|
||||
print(f" {'Entry':8} {'Wallet':15} {'Status':10} {'Cnt':5} {'Avg Amt':10} {'User'}")
|
||||
print(f" {'-'*8} {'-'*15} {'-'*10} {'-'*5} {'-'*10} {'-'*30}")
|
||||
for r in rows:
|
||||
print(f" {r[0]:8} {r[1]:15} {r[2]:10} {r[3]:5} {r[4]:10} {r[5] or 'N/A':30}")
|
||||
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
seed()
|
||||
Reference in New Issue
Block a user