Files
ai_ml_operations 3a14bfb996 Initial commit
2026-08-27 04:17:34 -07:00

117 lines
3.6 KiB
Python

"""Stripe invoice + Checkout pay-link helpers. Requires FEATURE_EMAIL_SMS to send."""
from __future__ import annotations
import logging
from datetime import date
from django.conf import settings
from django.urls import reverse
from django.utils import timezone
from payments.models import Invoice
logger = logging.getLogger(__name__)
class PaymentsError(RuntimeError):
pass
def _stripe():
secret = (settings.STRIPE_SECRET_KEY or "").strip()
if not secret:
raise PaymentsError("STRIPE_SECRET_KEY is not configured")
try:
import stripe
except ImportError as exc:
raise PaymentsError("stripe package is not installed") from exc
stripe.api_key = secret
return stripe
def next_invoice_number() -> str:
today = date.today().strftime("%Y%m%d")
prefix = f"INV-{today}-"
existing = Invoice.objects.filter(number__startswith=prefix).count()
return f"{prefix}{existing + 1:03d}"
def create_checkout_session(invoice: Invoice, *, success_url: str, cancel_url: str) -> str:
stripe = _stripe()
session = stripe.checkout.Session.create(
mode="payment",
customer_email=invoice.contact.email or None,
line_items=[
{
"quantity": 1,
"price_data": {
"currency": (invoice.currency or "usd").lower(),
"unit_amount": invoice.amount_cents,
"product_data": {
"name": invoice.description or f"Invoice {invoice.number}",
},
},
}
],
metadata={"invoice_id": str(invoice.pk), "invoice_number": invoice.number},
success_url=success_url,
cancel_url=cancel_url,
)
invoice.stripe_checkout_session_id = session.id
invoice.hosted_invoice_url = session.url or ""
invoice.status = Invoice.Status.OPEN
invoice.save(
update_fields=[
"stripe_checkout_session_id",
"hosted_invoice_url",
"status",
"updated_at",
]
)
return session.url or ""
def mark_paid(invoice: Invoice, *, stripe_id: str = "") -> None:
invoice.status = Invoice.Status.PAID
invoice.paid_at = timezone.now()
if stripe_id and not invoice.stripe_invoice_id:
invoice.stripe_invoice_id = stripe_id
invoice.save(
update_fields=["status", "paid_at", "stripe_invoice_id", "updated_at"]
)
def send_invoice_email(invoice: Invoice, pay_url: str) -> bool:
"""Send pay-link email through Django mail (SMTP2GO)."""
to_email = (invoice.contact.email or "").strip()
if not to_email:
raise PaymentsError("Contact has no email address")
from django.core.mail import EmailMultiAlternatives
name = invoice.contact.full_name or "there"
amount = f"{invoice.amount} {invoice.currency.upper()}"
subject = f"Invoice {invoice.number} from {settings.SITE_NAME}"
text = (
f"Hi {name},\n\n"
f"Invoice {invoice.number} for {amount} is ready.\n"
f"{invoice.description}\n\n"
f"Pay securely: {pay_url}\n"
)
html = (
f"<p>Hi {name},</p>"
f"<p>Invoice <strong>{invoice.number}</strong> for "
f"<strong>{amount}</strong> is ready.</p>"
f"<p>{invoice.description}</p>"
f'<p><a href="{pay_url}">Pay this invoice</a></p>'
)
mail = EmailMultiAlternatives(
subject=subject,
body=text,
from_email=settings.DEFAULT_FROM_EMAIL,
to=[to_email],
)
mail.attach_alternative(html, "text/html")
mail.send(fail_silently=False)
return True