Did some things...

This commit is contained in:
Joan
2025-09-15 22:45:46 +02:00
parent d3b4cd7eaa
commit 2bfdb539be
9 changed files with 410 additions and 195 deletions

View File

@@ -12,22 +12,23 @@ def format_raffle_details(raffle_id):
"""Fetches and formats raffle details for display, including multi-channel prices."""
raffle = get_raffle(raffle_id) # Fetches basic info from 'raffles' table
if not raffle:
return "Error: No se encontró la rifa."
return "Error: No se encontró el sorteo."
details = (
f" **Detalles de la rifa** \n\n"
f"**ID:** `{raffle['id']}`\n"
f"**Nombre:** {raffle['name']}\n"
f"**Descripción:**\n{raffle['description']}\n\n"
f"**Activo:** {'' if raffle['active'] else 'No (Terminado)'}\n"
f"**Precio por número (canal principal):** {raffle['price']}\n"
f" <b>Detalles del sorteo</b> \n\n"
f"<b>ID:</b> <code>{raffle['id']}</code>\n"
f"<b>Nombre:</b> {raffle['name']}\n"
f"<b>Descripción:</b>\n{raffle['description'][:100]}...\n\n"
f"<b>Envío internacional:</b> {'' if raffle['international_shipping'] else 'No'}\n"
f"<b>Activo:</b> {'' if raffle['active'] else 'No (Terminado)'}\n"
f"<b>Donación mínima (canal principal):</b> {raffle['price']}\n"
)
# Image ID (optional display)
if raffle['image_file_id']:
details += f"**ID Imagen:** (Presente)\n"
details += f"<b>ID Imagen:</b> {raffle['image_file_id']} (Presente)\n"
else:
details += f"**ID Imagen:** (No asignada)\n"
details += f"<b>ID Imagen:</b> (No asignada)\n"
# Add participant count and remaining numbers
participants = get_participants(raffle_id) # Fetches list of Rows
@@ -38,11 +39,25 @@ def format_raffle_details(raffle_id):
# pending_participants_count = sum(1 for p in participants if p['step'] == 'waiting_for_payment')
details += f"\n**Participantes Confirmados:** {completed_participants_count}\n"
# details += f"**Reservas Pendientes:** {pending_participants_count}\n"
details += f"\n<b>Participantes Confirmados:</b> {completed_participants_count}\n"
# details += f"<b>Reservas Pendientes:</b> {pending_participants_count}\n"
remaining_count = get_remaining_numbers_amount(raffle_id)
details += f"**Números Disponibles:** {remaining_count if remaining_count >= 0 else 'Error al calcular'}\n"
details += f"<b>Números Disponibles:</b> {remaining_count if remaining_count >= 0 else 'Error al calcular'}\n"
# Gross and net amounts
total_gross = 0.0
total_fees = 0.0
total_net = 0.0
invoice_ids = get_all_invoice_ids(raffle_id)
for inv_id in invoice_ids:
gross, net, fees = get_paypal_amounts_for_invoice(inv_id)
total_gross += gross
total_fees += fees
total_net += net
details += f"\n<b>Total Recaudado (bruto):</b> {total_gross:.2f}\n"
details += f"<b>Total Gastos (comisiones):</b> {total_fees:.2f}\n"
details += f"<b>Total Beneficio (neto):</b> {total_net:.2f}\n"
return details
@@ -131,12 +146,12 @@ def get_winners(raffle_id, winner_numbers_int):
# if not raffle_details:
# logger.error(f"Cannot generate image: Raffle {raffle_id} not found.")
# # Draw error message on image
# draw.text((10, 10), f"Error: Rifa {raffle_id} no encontrado", fill="red", font=title_font)
# draw.text((10, 10), f"Error: Sorteo {raffle_id} no encontrado", fill="red", font=title_font)
# img.save(f"/app/data/raffles/raffle_table_{raffle_id}_error.png")
# return False # Indicate failure
# raffle_name = raffle_details['name']
# title_text = f"Rifa: {raffle_name}"
# title_text = f"Sorteo: {raffle_name}"
# # Calculate text bounding box for centering
# try:
# # Use textbbox for more accurate centering
@@ -262,12 +277,12 @@ def generate_table_image(raffle_id):
# --- Title Bar ---
raffle_details = get_raffle(raffle_id)
if not raffle_details:
draw.text((10, 10), f"Error: Rifa {raffle_id} no encontrada", fill="red", font=title_font)
draw.text((10, 10), f"Error: Sorteo {raffle_id} no encontrado", fill="red", font=title_font)
img.save(f"/app/data/raffles/raffle_table_{raffle_id}_error.png")
return False
raffle_name = raffle_details['name']
title_text = f"Rifa: {raffle_name}"
title_text = f"Sorteo: {raffle_name}"
# Draw title bar (full width)
title_bar_color = "#4a90e2"
@@ -403,7 +418,7 @@ def get_paypal_access_token():
logger.info(f"Using cached PayPal access token")
return old_token
logger.info("Fetching new PayPal access token")
url = "https://api-m.sandbox.paypal.com/v1/oauth2/token"
url = f"{PAYPAL_URL}/v1/oauth2/token"
headers = {"Accept": "application/json", "Accept-Language": "en_US"}
data = {"grant_type": "client_credentials"}
@@ -413,8 +428,8 @@ def get_paypal_access_token():
store_paypal_access_token(response.json()["access_token"], response.json()["expires_in"])
return response.json()["access_token"]
def create_paypal_order(access_token, value):
url = "https://api-m.sandbox.paypal.com/v2/checkout/orders"
def create_paypal_order(access_token, value, raffle_id, numbers):
url = f"{PAYPAL_URL}/v2/checkout/orders"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {access_token}"
@@ -423,10 +438,12 @@ def create_paypal_order(access_token, value):
"intent": "CAPTURE",
"purchase_units": [
{
"amount": {"currency_code": "EUR", "value": f"{value:.2f}"}
"amount": {"currency_code": "EUR", "value": f"{value:.2f}"},
"description": f"Donación para participar en el sorteo de HomeLabs Club (ID: {raffle_id}, Números: {numbers})",
}
],
"application_context": {
"locale": "es-ES",
"return_url": f"https://t.me/{BOT_NAME}",
"cancel_url": f"https://t.me/{BOT_NAME}"
}
@@ -439,3 +456,45 @@ def create_paypal_order(access_token, value):
# Extract the approval link
approval_url = next(link["href"] for link in order["links"] if link["rel"] == "approve")
return approval_url, order["id"]
def get_paypal_amounts_for_invoice(invoice_id):
"""Fetches the gross, net, and fee amounts for a given PayPal invoice ID."""
access_token = get_paypal_access_token()
url = f"{PAYPAL_URL}/v2/checkout/orders/{invoice_id}"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {access_token}"
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
except requests.RequestException as e:
logger.error(f"Error fetching PayPal invoice {invoice_id}: {e}")
return 0.0, 0.0, 0.0
order = response.json()
if order["status"] != "COMPLETED":
logger.warning(f"Invoice {invoice_id} is not completed. Status: {order['status']}")
return 0.0, 0.0, 0.0
gross_amount = float(order["purchase_units"][0]["amount"]["value"])
fee_amount = 0.0
net_amount = gross_amount
# Fetch capture details to get fee information
capture_id = order["purchase_units"][0]["payments"]["captures"][0]["id"]
capture_url = f"{PAYPAL_URL}/v2/payments/captures/{capture_id}"
capture_response = requests.get(capture_url, headers=headers)
capture_response.raise_for_status()
capture_details = capture_response.json()
if "seller_receivable_breakdown" in capture_details:
breakdown = capture_details["seller_receivable_breakdown"]
fee_amount = float(breakdown.get("paypal_fee", {}).get("value", 0.0))
net_amount = float(breakdown.get("net_amount", {}).get("value", gross_amount))
return gross_amount, net_amount, fee_amount