import pytest from infrasynth.billing.invoice_generator import _build_invoice_pdf from infrasynth.billing.models import App, Invoice, PaymentGateway, Plan from infrasynth.billing.services import BillingService from infrasynth.shared.enums import MonetizationModel pytestmark = pytest.mark.django_db @pytest.fixture def gateway(): return PaymentGateway.objects.create( slug="fake", display_name="Fake", gateway_class="tests.helpers.FakeGateway", is_active=True, ) @pytest.fixture def app(): return App.objects.create(slug="messenger", name="Messenger", monetization=MonetizationModel.SUBSCRIPTION) @pytest.fixture def plan(app, gateway): return Plan.objects.create( app=app, slug="pro", name="Pro", price_amount=4900, price_currency="USD", interval="monthly", gateway=gateway, ) class TestBuildInvoicePdf: def test_generates_pdf_bytes(self, tenant, gateway, plan): subscription = BillingService().create_subscription(plan, tenant, gateway) invoice = Invoice.all_objects.create( tenant=tenant, subscription=subscription, gateway=gateway, invoice_number="INV-2026-000001", amount=4900, currency="USD", status="open", line_items=[{"description": "Pro", "amount": 4900, "quantity": 1}], ) pdf_bytes = _build_invoice_pdf(invoice) assert pdf_bytes.startswith(b"%PDF") assert len(pdf_bytes) > 100 def test_pdf_includes_tax(self, tenant, gateway, plan): subscription = BillingService().create_subscription(plan, tenant, gateway) invoice = Invoice.all_objects.create( tenant=tenant, subscription=subscription, gateway=gateway, invoice_number="INV-2026-000002", amount=10000, tax_amount=1900, tax_name="IVA", currency="USD", status="open", line_items=[{"description": "Plan", "amount": 10000, "quantity": 1}], ) pdf_bytes = _build_invoice_pdf(invoice) assert pdf_bytes.startswith(b"%PDF") class TestGenerateInvoicePdfTask: def test_task_generates_and_attaches_pdf(self, tenant, gateway, plan, media_root): subscription = BillingService().create_subscription(plan, tenant, gateway) invoice = BillingService().generate_invoice(subscription) invoice.refresh_from_db() assert invoice.pdf_file_id is not None assert invoice.pdf_file.original_filename.startswith("invoice_") assert invoice.pdf_file.mime_type == "application/pdf" assert invoice.pdf_file.size_bytes > 100 def test_task_missing_invoice_returns_none(self): from infrasynth.billing.invoice_generator import generate_invoice_pdf assert generate_invoice_pdf.run(999999) is None