STripe Paymen and PK payemtns and many othe rbacekd and froentened issues
This commit is contained in:
@@ -14,6 +14,40 @@ from ....auth.models import Account, Subscription
|
||||
class InvoiceService:
|
||||
"""Service for managing invoices"""
|
||||
|
||||
@staticmethod
|
||||
def get_pending_invoice(subscription: Subscription) -> Optional[Invoice]:
|
||||
"""
|
||||
Get pending invoice for a subscription.
|
||||
Used to find existing invoice during payment processing instead of creating duplicates.
|
||||
"""
|
||||
return Invoice.objects.filter(
|
||||
subscription=subscription,
|
||||
status='pending'
|
||||
).order_by('-created_at').first()
|
||||
|
||||
@staticmethod
|
||||
def get_or_create_subscription_invoice(
|
||||
subscription: Subscription,
|
||||
billing_period_start: datetime,
|
||||
billing_period_end: datetime
|
||||
) -> tuple[Invoice, bool]:
|
||||
"""
|
||||
Get existing pending invoice or create new one.
|
||||
Returns tuple of (invoice, created) where created is True if new invoice was created.
|
||||
"""
|
||||
# First try to find existing pending invoice for this subscription
|
||||
existing = InvoiceService.get_pending_invoice(subscription)
|
||||
if existing:
|
||||
return existing, False
|
||||
|
||||
# Create new invoice if none exists
|
||||
invoice = InvoiceService.create_subscription_invoice(
|
||||
subscription=subscription,
|
||||
billing_period_start=billing_period_start,
|
||||
billing_period_end=billing_period_end
|
||||
)
|
||||
return invoice, True
|
||||
|
||||
@staticmethod
|
||||
def generate_invoice_number(account: Account) -> str:
|
||||
"""
|
||||
@@ -52,6 +86,10 @@ class InvoiceService:
|
||||
) -> Invoice:
|
||||
"""
|
||||
Create invoice for subscription billing period
|
||||
|
||||
Currency logic:
|
||||
- USD for online payments (stripe, paypal)
|
||||
- Local currency (PKR) only for bank_transfer in applicable countries
|
||||
"""
|
||||
account = subscription.account
|
||||
plan = subscription.plan
|
||||
@@ -74,12 +112,22 @@ class InvoiceService:
|
||||
invoice_date = timezone.now().date()
|
||||
due_date = invoice_date + timedelta(days=INVOICE_DUE_DATE_OFFSET)
|
||||
|
||||
# Get currency based on billing country
|
||||
# Determine currency based on payment method:
|
||||
# - Online payments (stripe, paypal): Always USD
|
||||
# - Manual payments (bank_transfer, local_wallet): Local currency for applicable countries
|
||||
from igny8_core.business.billing.utils.currency import get_currency_for_country, convert_usd_to_local
|
||||
currency = get_currency_for_country(account.billing_country)
|
||||
|
||||
# Convert plan price to local currency
|
||||
local_price = convert_usd_to_local(float(plan.price), account.billing_country)
|
||||
payment_method = account.payment_method
|
||||
online_payment_methods = ['stripe', 'paypal']
|
||||
|
||||
if payment_method in online_payment_methods:
|
||||
# Online payments are always in USD
|
||||
currency = 'USD'
|
||||
local_price = float(plan.price)
|
||||
else:
|
||||
# Manual payments use local currency for applicable countries
|
||||
currency = get_currency_for_country(account.billing_country)
|
||||
local_price = convert_usd_to_local(float(plan.price), account.billing_country)
|
||||
|
||||
invoice = Invoice.objects.create(
|
||||
account=account,
|
||||
@@ -95,7 +143,8 @@ class InvoiceService:
|
||||
'billing_period_end': billing_period_end.isoformat(),
|
||||
'subscription_id': subscription.id, # Keep in metadata for backward compatibility
|
||||
'usd_price': str(plan.price), # Store original USD price
|
||||
'exchange_rate': str(local_price / float(plan.price) if plan.price > 0 else 1.0)
|
||||
'exchange_rate': str(local_price / float(plan.price) if plan.price > 0 else 1.0),
|
||||
'payment_method': payment_method
|
||||
}
|
||||
)
|
||||
|
||||
@@ -120,16 +169,28 @@ class InvoiceService:
|
||||
) -> Invoice:
|
||||
"""
|
||||
Create invoice for credit package purchase
|
||||
|
||||
Currency logic:
|
||||
- USD for online payments (stripe, paypal)
|
||||
- Local currency (PKR) only for bank_transfer in applicable countries
|
||||
"""
|
||||
from igny8_core.business.billing.config import INVOICE_DUE_DATE_OFFSET
|
||||
invoice_date = timezone.now().date()
|
||||
|
||||
# Get currency based on billing country
|
||||
# Determine currency based on payment method
|
||||
from igny8_core.business.billing.utils.currency import get_currency_for_country, convert_usd_to_local
|
||||
currency = get_currency_for_country(account.billing_country)
|
||||
|
||||
# Convert credit package price to local currency
|
||||
local_price = convert_usd_to_local(float(credit_package.price), account.billing_country)
|
||||
payment_method = account.payment_method
|
||||
online_payment_methods = ['stripe', 'paypal']
|
||||
|
||||
if payment_method in online_payment_methods:
|
||||
# Online payments are always in USD
|
||||
currency = 'USD'
|
||||
local_price = float(credit_package.price)
|
||||
else:
|
||||
# Manual payments use local currency for applicable countries
|
||||
currency = get_currency_for_country(account.billing_country)
|
||||
local_price = convert_usd_to_local(float(credit_package.price), account.billing_country)
|
||||
|
||||
invoice = Invoice.objects.create(
|
||||
account=account,
|
||||
@@ -143,7 +204,8 @@ class InvoiceService:
|
||||
'credit_package_id': credit_package.id,
|
||||
'credit_amount': credit_package.credits,
|
||||
'usd_price': str(credit_package.price), # Store original USD price
|
||||
'exchange_rate': str(local_price / float(credit_package.price) if credit_package.price > 0 else 1.0)
|
||||
'exchange_rate': str(local_price / float(credit_package.price) if credit_package.price > 0 else 1.0),
|
||||
'payment_method': payment_method
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user