Azure Blob Storage
RoundTrip uses Azure Blob Storage for storing generated invoice PDFs. The storage account is provisioned in the rg-roundtrip-production resource group and is accessed by the API via a connection string stored in Key Vault.
What Blob Storage Holds
| Container | Contents | Access |
|---|---|---|
invoice-pdfs | Generated invoice PDFs, named {tenantId}/{invoiceId}.pdf | Private — accessed via API only |
Configuration
Key Vault Secret
| Secret Name | Config Key | Purpose |
|---|---|---|
ConnectionStrings--BlobStorage | ConnectionStrings:BlobStorage | Azure Storage account connection string |
App Service Setting
| Setting Name | Value |
|---|---|
ConnectionStrings__BlobStorage | @Microsoft.KeyVault(VaultName=kv-roundtrip-production;SecretName=ConnectionStrings--BlobStorage) |
Invoice PDF Flow
1. Ticket completed → TicketCompletedEvent raised
│
▼
2. Domain event handler → Hangfire.Enqueue<GenerateInvoicePdfJob>
│
▼
3. GenerateInvoicePdfJob
│ Loads invoice from database
│ Generates PDF via QuestPDF
│ Uploads to blob: invoice-pdfs/{tenantId}/{invoiceId}.pdf
│
▼
4. SendInvoiceEmailJob (runs separately)
│ Checks blob for invoice-pdfs/{tenantId}/{invoiceId}.pdf
│ If found → attaches PDF to email
│ If not yet available → sends email without attachment (logs warning)
Blob Naming Convention
Container: invoice-pdfs
Blob path: {tenantId}/{invoiceId}.pdf
Example:
ad05b136-e770-4650-b563-75b7dad17234/b5a1725b-f8b3-44a7-a54e-0d87bc9c3e4f.pdf
└─ tenantId └─ invoiceId
Storage Account
| Item | Detail |
|---|---|
| Resource name | stroundtripproduction |
| Resource group | rg-roundtrip-production |
| Region | Central US |
| Access | Via connection string — Managed Identity access planned |
| Login | Azure Portal → Traxs Group Subscription → stroundtripproduction |
Troubleshooting
"Blob not found in container invoice-pdfs"
This warning appears in logs when the invoice email job runs before the PDF generation job completes. It is not an error — the email is sent without the PDF attachment.
If the PDF never appears in blob storage:
- Check Hangfire dashboard for
GenerateInvoicePdfJobfailures - Check App Service logs for QuestPDF rendering errors
- Verify
ConnectionStrings__BlobStorageApp Service setting resolves correctly (green Key Vault checkmark) - Check that the
invoice-pdfscontainer exists in the storage account
Viewing blobs in storage
Use Azure Storage Explorer or the Azure Portal:
- Azure Portal →
stroundtripproduction→ Containers →invoice-pdfs - Navigate to
{tenantId}/folder to find invoices for a specific tenant
Planned Enhancements
| Enhancement | Notes |
|---|---|
| Switch to Managed Identity access | Replace connection string with Managed Identity for improved security posture |
| Signed URL for PDF download | Generate short-lived SAS URLs for direct PDF download links in the app |
| Attachment storage | Store job site photos and ticket attachments uploaded by technicians |