Open Source CRM developed on Django framework with REST API for contact, lead, account, and opportunity management
Invoice creation, management, and billing operations for the Django CRM system. Provides complete invoice lifecycle management from creation through payment with email notifications, PDF generation, and status tracking.
Important Note: The invoice API endpoints are fully implemented with models, serializers, and API views, but are not currently routed in the main application URLs. To enable invoice API functionality, add the invoice URLs to the main URL routing configuration.
List invoices with comprehensive filtering and search capabilities.
def list_invoices(status: str = None, name: str = None,
assigned_to: str = None, limit: int = 10, offset: int = 0) -> dict:
"""
List invoices with filtering and search.
Args:
status (str, optional): Filter by invoice status ('Draft', 'Sent', 'Paid', 'Pending', 'Cancelled')
name (str, optional): Filter by customer name (partial match)
assigned_to (str, optional): Filter by assigned user UUID
limit (int): Number of results per page (default: 10)
offset (int): Number of results to skip (default: 0)
Returns:
dict: Paginated invoices with metadata
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
GET /api/invoices/?status=Draft&name=acme&limit=5
Response:
{
"count": 25,
"next": "/api/invoices/?limit=5&offset=5",
"previous": null,
"results": [
{
"id": "invoice-uuid",
"invoice_title": "Monthly Service",
"invoice_number": "INV-001",
"status": "Draft",
"due_date": "2024-01-15",
"name": "ACME Corporation",
"email": "billing@acme.com",
"phone": "+1234567890",
"quantity": 40,
"rate": "150.00",
"total_amount": "6000.00",
"currency": "USD",
"created_on": "2024-01-01T10:00:00Z",
"assigned_to": ["user-uuid"],
"teams": ["team-uuid"]
}
]
}
"""Create new invoices with billing details and customer information.
def create_invoice(invoice_data: dict) -> dict:
"""
Create a new invoice.
Args:
invoice_data (dict): Invoice information including:
- invoice_title: str
- invoice_number: str (optional, auto-generated if not provided)
- name: str (customer name)
- email: str (customer email)
- phone: str (optional)
- quantity: int (hours or units)
- rate: decimal (rate per unit)
- currency: str (3-letter currency code)
- due_date: str (YYYY-MM-DD format)
- status: str (default: 'Draft')
- assigned_to: list[str] (user UUIDs)
- teams: list[str] (team UUIDs)
- from_address: dict (billing address)
- to_address: dict (customer address)
Returns:
dict: Created invoice details
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
POST /api/invoices/
{
"invoice_title": "Web Development Services",
"name": "Tech Solutions Inc",
"email": "billing@techsolutions.com",
"quantity": 80,
"rate": "125.00",
"currency": "USD",
"due_date": "2024-02-15",
"assigned_to": ["user-uuid"],
"teams": ["dev-team-uuid"]
}
"""Retrieve detailed information about a specific invoice.
def get_invoice_details(invoice_id: str) -> dict:
"""
Get detailed invoice information.
Args:
invoice_id (str): Invoice UUID
Returns:
dict: Complete invoice details including addresses, history, and assignments
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
GET /api/invoices/invoice-uuid/
Response includes full invoice data, billing addresses, assigned users,
teams, and invoice history
"""Update existing invoice information and details.
def update_invoice(invoice_id: str, update_data: dict) -> dict:
"""
Update invoice information.
Args:
invoice_id (str): Invoice UUID
update_data (dict): Fields to update (same structure as create)
Returns:
dict: Updated invoice details
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
PUT /api/invoices/invoice-uuid/
{
"status": "Sent",
"total_amount": "6500.00"
}
"""Remove invoices from the system.
def delete_invoice(invoice_id: str) -> dict:
"""
Delete an invoice.
Args:
invoice_id (str): Invoice UUID
Returns:
dict: Deletion confirmation
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
DELETE /api/invoices/invoice-uuid/
"""Send invoices via email with PDF attachments.
def send_invoice_email(invoice_id: str, email_data: dict) -> dict:
"""
Send invoice by email.
Args:
invoice_id (str): Invoice UUID
email_data (dict): Email configuration including recipients and message
Returns:
dict: Email sending confirmation
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
POST /api/invoices/invoice-uuid/send-mail/
{
"recipients": ["customer@example.com"],
"subject": "Invoice INV-001",
"message": "Please find attached invoice"
}
"""Generate and download invoice PDFs.
def download_invoice_pdf(invoice_id: str) -> bytes:
"""
Generate and download invoice PDF.
Args:
invoice_id (str): Invoice UUID
Returns:
bytes: PDF file content
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
POST /api/invoices/invoice-uuid/download/
Response: PDF file download
"""Update invoice status through the billing lifecycle.
def update_invoice_status(invoice_id: str, status_data: dict) -> dict:
"""
Update invoice status.
Args:
invoice_id (str): Invoice UUID
status_data (dict): Status information
- status: str ('Draft', 'Sent', 'Paid', 'Pending', 'Cancelled')
Returns:
dict: Updated invoice with new status
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
POST /api/invoices/invoice-uuid/status/
{
"status": "Paid"
}
"""Add comments and notes to invoices for collaboration and tracking.
def add_invoice_comment(invoice_id: str, comment_data: dict) -> dict:
"""
Add a comment to an invoice.
Args:
invoice_id (str): Invoice UUID
comment_data (dict): Comment information
- comment: str (comment text)
Returns:
dict: Created comment details
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Example:
POST /api/invoices/comment/invoice-uuid/
{
"comment": "Customer requested payment extension"
}
"""Upload and manage files attached to invoices.
def add_invoice_attachment(invoice_id: str, file_data: dict) -> dict:
"""
Add a file attachment to an invoice.
Args:
invoice_id (str): Invoice UUID
file_data (dict): File upload data
- attachment: file (uploaded file)
Returns:
dict: Created attachment details
Headers Required:
Authorization: Bearer <access_token>
organization-id: <org_uuid>
Content-Type: multipart/form-data
Example:
POST /api/invoices/attachment/invoice-uuid/
(multipart form data with file upload)
"""class Invoice:
"""Invoice model for billing operations"""
id: str # UUID
invoice_title: str
invoice_number: str
status: str # 'Draft', 'Sent', 'Paid', 'Pending', 'Cancelled'
due_date: str # YYYY-MM-DD format
name: str # Customer name
email: str # Customer email
phone: str # Customer phone (optional)
quantity: int # Hours or units
rate: str # Decimal rate per unit
total_amount: str # Calculated total (rate * quantity)
tax: str # Tax amount (optional)
currency: str # 3-letter currency code
created_on: str # ISO datetime
created_by: User
org: Organization
assigned_to: list[User] # Assigned users
teams: list[Team] # Associated teams
from_address: Address # Billing address
to_address: Address # Customer address
class InvoiceHistory:
"""Invoice status change tracking"""
id: str # UUID
invoice: str # Invoice UUID
updated_by: User
updated_on: str # ISO datetime
status_changed_from: str # Previous status
status_changed_to: str # New statusimport requests
headers = {
'Authorization': 'Bearer your-access-token',
'organization-id': 'your-org-uuid',
'Content-Type': 'application/json'
}
# Create a new invoice
invoice_data = {
"invoice_title": "Q1 Consulting Services",
"name": "Global Tech Corp",
"email": "finance@globaltech.com",
"quantity": 120,
"rate": "200.00",
"currency": "USD",
"due_date": "2024-02-28",
"assigned_to": ["user-uuid"]
}
response = requests.post('http://your-crm.com/api/invoices/',
json=invoice_data, headers=headers)
invoice = response.json()
invoice_id = invoice['id']
# Update invoice status to sent
status_update = {"status": "Sent"}
requests.post(f'http://your-crm.com/api/invoices/{invoice_id}/status/',
json=status_update, headers=headers)
# Send invoice via email
email_data = {
"recipients": ["finance@globaltech.com"],
"subject": f"Invoice {invoice['invoice_number']}",
"message": "Please find your invoice attached. Payment due within 30 days."
}
requests.post(f'http://your-crm.com/api/invoices/{invoice_id}/send-mail/',
json=email_data, headers=headers)
# Add payment tracking comment
comment_data = {"comment": "Payment reminder sent via email"}
requests.post(f'http://your-crm.com/api/invoices/comment/{invoice_id}/',
json=comment_data, headers=headers)Common error responses include:
400 Bad Request: Invalid invoice data or missing required fields401 Unauthorized: Missing or invalid authentication token403 Forbidden: Insufficient permissions for invoice operations404 Not Found: Invoice not found or not accessible422 Unprocessable Entity: Validation errors in invoice dataAll error responses follow the standard format with field-specific validation details.
Install with Tessl CLI
npx tessl i tessl/pypi-django-crm