billing admin account 1
This commit is contained in:
@@ -52,6 +52,8 @@ class InvoiceService:
|
||||
billing_email=account.billing_email or account.users.filter(role='owner').first().email,
|
||||
status='pending',
|
||||
currency='USD',
|
||||
invoice_date=timezone.now().date(),
|
||||
due_date=billing_period_end.date(),
|
||||
billing_period_start=billing_period_start,
|
||||
billing_period_end=billing_period_end
|
||||
)
|
||||
@@ -83,7 +85,13 @@ class InvoiceService:
|
||||
invoice_number=InvoiceService.generate_invoice_number(account),
|
||||
billing_email=account.billing_email or account.users.filter(role='owner').first().email,
|
||||
status='pending',
|
||||
currency='USD'
|
||||
currency='USD',
|
||||
invoice_date=timezone.now().date(),
|
||||
due_date=timezone.now().date(),
|
||||
metadata={
|
||||
'credit_package_id': credit_package.id,
|
||||
'credit_amount': credit_package.credits,
|
||||
},
|
||||
)
|
||||
|
||||
# Add line item for credit package
|
||||
@@ -125,6 +133,7 @@ class InvoiceService:
|
||||
status='draft',
|
||||
currency='USD',
|
||||
notes=notes,
|
||||
invoice_date=timezone.now().date(),
|
||||
due_date=due_date or (timezone.now() + timedelta(days=30))
|
||||
)
|
||||
|
||||
|
||||
@@ -77,6 +77,12 @@ class PaymentService:
|
||||
if payment_method not in ['bank_transfer', 'local_wallet', 'manual']:
|
||||
raise ValueError("Invalid manual payment method")
|
||||
|
||||
meta = metadata or {}
|
||||
# propagate credit package metadata from invoice if present
|
||||
if invoice.metadata.get('credit_package_id'):
|
||||
meta.setdefault('credit_package_id', invoice.metadata.get('credit_package_id'))
|
||||
meta.setdefault('credit_amount', invoice.metadata.get('credit_amount'))
|
||||
|
||||
payment = Payment.objects.create(
|
||||
account=invoice.account,
|
||||
invoice=invoice,
|
||||
@@ -86,7 +92,7 @@ class PaymentService:
|
||||
status='pending_approval',
|
||||
transaction_reference=transaction_reference,
|
||||
admin_notes=admin_notes,
|
||||
metadata=metadata or {}
|
||||
metadata=meta
|
||||
)
|
||||
|
||||
return payment
|
||||
@@ -102,7 +108,7 @@ class PaymentService:
|
||||
"""
|
||||
from .invoice_service import InvoiceService
|
||||
|
||||
payment.status = 'completed'
|
||||
payment.status = 'succeeded'
|
||||
payment.processed_at = timezone.now()
|
||||
|
||||
if transaction_id:
|
||||
@@ -153,9 +159,10 @@ class PaymentService:
|
||||
if payment.status != 'pending_approval':
|
||||
raise ValueError("Payment is not pending approval")
|
||||
|
||||
payment.status = 'completed'
|
||||
payment.status = 'succeeded'
|
||||
payment.processed_at = timezone.now()
|
||||
payment.approved_by_id = approved_by_user_id
|
||||
payment.approved_at = timezone.now()
|
||||
|
||||
if admin_notes:
|
||||
payment.admin_notes = f"{payment.admin_notes}\n\nApproval notes: {admin_notes}" if payment.admin_notes else admin_notes
|
||||
@@ -212,6 +219,11 @@ class PaymentService:
|
||||
except CreditPackage.DoesNotExist:
|
||||
return
|
||||
|
||||
# Update account balance
|
||||
account: Account = payment.account
|
||||
account.credits = (account.credits or 0) + credit_package.credits
|
||||
account.save(update_fields=['credits', 'updated_at'])
|
||||
|
||||
# Create credit transaction
|
||||
CreditTransaction.objects.create(
|
||||
account=payment.account,
|
||||
@@ -244,14 +256,20 @@ class PaymentService:
|
||||
return {
|
||||
'methods': [
|
||||
{
|
||||
'id': 'stripe-default',
|
||||
'type': 'stripe',
|
||||
'name': 'Credit/Debit Card',
|
||||
'instructions': 'Pay securely with your credit or debit card'
|
||||
'display_name': 'Credit/Debit Card',
|
||||
'instructions': 'Pay securely with your credit or debit card',
|
||||
'is_enabled': True,
|
||||
},
|
||||
{
|
||||
'id': 'paypal-default',
|
||||
'type': 'paypal',
|
||||
'name': 'PayPal',
|
||||
'instructions': 'Pay with your PayPal account'
|
||||
'display_name': 'PayPal',
|
||||
'instructions': 'Pay with your PayPal account',
|
||||
'is_enabled': True,
|
||||
}
|
||||
],
|
||||
'stripe': True,
|
||||
@@ -272,9 +290,12 @@ class PaymentService:
|
||||
for config in configs:
|
||||
method_flags[config.payment_method] = True
|
||||
method_data = {
|
||||
'id': f"{config.country_code}-{config.payment_method}-{config.id}",
|
||||
'type': config.payment_method,
|
||||
'name': config.display_name or config.get_payment_method_display(),
|
||||
'instructions': config.instructions
|
||||
'display_name': config.display_name or config.get_payment_method_display(),
|
||||
'instructions': config.instructions,
|
||||
'is_enabled': True,
|
||||
}
|
||||
|
||||
# Add bank details if bank_transfer
|
||||
@@ -323,8 +344,8 @@ class PaymentService:
|
||||
TODO: Implement actual refund logic for Stripe/PayPal
|
||||
For now, just mark as refunded
|
||||
"""
|
||||
if payment.status != 'completed':
|
||||
raise ValueError("Can only refund completed payments")
|
||||
if payment.status not in ['completed', 'succeeded']:
|
||||
raise ValueError("Can only refund succeeded/complete payments")
|
||||
|
||||
refund_amount = amount or payment.amount
|
||||
|
||||
@@ -338,8 +359,9 @@ class PaymentService:
|
||||
amount=-refund_amount, # Negative amount for refund
|
||||
currency=payment.currency,
|
||||
payment_method=payment.payment_method,
|
||||
status='completed',
|
||||
status='refunded',
|
||||
processed_at=timezone.now(),
|
||||
refunded_at=timezone.now(),
|
||||
metadata={
|
||||
'refund_for_payment_id': payment.id,
|
||||
'refund_reason': reason,
|
||||
@@ -348,10 +370,16 @@ class PaymentService:
|
||||
)
|
||||
|
||||
# Update original payment metadata
|
||||
payment.metadata['refunded'] = True
|
||||
payment.metadata['refund_payment_id'] = refund.id
|
||||
payment.metadata['refund_amount'] = str(refund_amount)
|
||||
payment.save()
|
||||
meta = payment.metadata or {}
|
||||
meta['refunded'] = True
|
||||
meta['refund_payment_id'] = refund.id
|
||||
meta['refund_amount'] = str(refund_amount)
|
||||
if reason:
|
||||
meta['refund_reason'] = reason
|
||||
payment.metadata = meta
|
||||
payment.status = 'refunded'
|
||||
payment.refunded_at = timezone.now()
|
||||
payment.save(update_fields=['metadata', 'status', 'refunded_at', 'updated_at'])
|
||||
|
||||
return refund
|
||||
|
||||
|
||||
Reference in New Issue
Block a user