billing admin account 1
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Billing Models for Credit System
|
||||
"""
|
||||
from decimal import Decimal
|
||||
from django.db import models
|
||||
from django.core.validators import MinValueValidator
|
||||
from django.conf import settings
|
||||
@@ -22,6 +23,11 @@ class CreditTransaction(AccountBaseModel):
|
||||
balance_after = models.IntegerField(help_text="Credit balance after this transaction")
|
||||
description = models.CharField(max_length=255)
|
||||
metadata = models.JSONField(default=dict, help_text="Additional context (AI call details, etc.)")
|
||||
reference_id = models.CharField(
|
||||
max_length=255,
|
||||
blank=True,
|
||||
help_text="Optional reference (e.g., payment id, invoice id)"
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
@@ -183,9 +189,10 @@ class Invoice(AccountBaseModel):
|
||||
)
|
||||
|
||||
# Amounts
|
||||
subtotal = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
subtotal = models.DecimalField(max_digits=10, decimal_places=2, default=0)
|
||||
tax = models.DecimalField(max_digits=10, decimal_places=2, default=0)
|
||||
total = models.DecimalField(max_digits=10, decimal_places=2)
|
||||
total = models.DecimalField(max_digits=10, decimal_places=2, default=0)
|
||||
currency = models.CharField(max_length=3, default='USD')
|
||||
|
||||
# Status
|
||||
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', db_index=True)
|
||||
@@ -201,6 +208,9 @@ class Invoice(AccountBaseModel):
|
||||
# Payment integration
|
||||
stripe_invoice_id = models.CharField(max_length=255, null=True, blank=True)
|
||||
payment_method = models.CharField(max_length=50, null=True, blank=True)
|
||||
billing_email = models.EmailField(null=True, blank=True)
|
||||
billing_period_start = models.DateTimeField(null=True, blank=True)
|
||||
billing_period_end = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
# Metadata
|
||||
notes = models.TextField(blank=True)
|
||||
@@ -222,6 +232,45 @@ class Invoice(AccountBaseModel):
|
||||
def __str__(self):
|
||||
return f"Invoice {self.invoice_number} - {self.account.name if self.account else 'No Account'}"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Helpers to keep service code working with legacy field names
|
||||
# ------------------------------------------------------------------
|
||||
@property
|
||||
def subtotal_amount(self):
|
||||
return self.subtotal
|
||||
|
||||
@property
|
||||
def tax_amount(self):
|
||||
return self.tax
|
||||
|
||||
@property
|
||||
def total_amount(self):
|
||||
return self.total
|
||||
|
||||
def add_line_item(self, description: str, quantity: int, unit_price: Decimal, amount: Decimal = None):
|
||||
"""Append a line item and keep JSON shape consistent."""
|
||||
items = list(self.line_items or [])
|
||||
qty = quantity or 1
|
||||
amt = Decimal(amount) if amount is not None else Decimal(unit_price) * qty
|
||||
items.append({
|
||||
'description': description,
|
||||
'quantity': qty,
|
||||
'unit_price': str(unit_price),
|
||||
'amount': str(amt),
|
||||
})
|
||||
self.line_items = items
|
||||
|
||||
def calculate_totals(self):
|
||||
"""Recompute subtotal, tax, and total from line_items."""
|
||||
subtotal = Decimal('0')
|
||||
for item in self.line_items or []:
|
||||
try:
|
||||
subtotal += Decimal(str(item.get('amount') or 0))
|
||||
except Exception:
|
||||
pass
|
||||
self.subtotal = subtotal
|
||||
self.total = subtotal + (self.tax or Decimal('0'))
|
||||
|
||||
|
||||
class Payment(AccountBaseModel):
|
||||
"""
|
||||
@@ -230,8 +279,10 @@ class Payment(AccountBaseModel):
|
||||
"""
|
||||
STATUS_CHOICES = [
|
||||
('pending', 'Pending'),
|
||||
('pending_approval', 'Pending Approval'),
|
||||
('processing', 'Processing'),
|
||||
('succeeded', 'Succeeded'),
|
||||
('completed', 'Completed'), # Legacy alias for succeeded
|
||||
('failed', 'Failed'),
|
||||
('refunded', 'Refunded'),
|
||||
('cancelled', 'Cancelled'),
|
||||
@@ -272,6 +323,8 @@ class Payment(AccountBaseModel):
|
||||
help_text="Bank transfer reference, wallet transaction ID, etc."
|
||||
)
|
||||
manual_notes = models.TextField(blank=True, help_text="Admin notes for manual payments")
|
||||
transaction_reference = models.CharField(max_length=255, blank=True)
|
||||
admin_notes = models.TextField(blank=True, help_text="Internal notes on approval/rejection")
|
||||
approved_by = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
null=True,
|
||||
|
||||
Reference in New Issue
Block a user