Django Oscar Accounts is a package that provides the ability to manage accounts with fully managed account functionality to use with Django Oscar.
* Django Oscar Accounts provides managed accounts using double-entry bookkeeping.
* In this package every transaction is recorded twice(once for the source account and once for the destination account) by using double-entry bookkeeping. This make sure that books always balance and there exist full record of all transactions.
Features -
Installation -
* Install using pip:
pip install django-oscar-accounts
* Next, add "oscar_accounts" to INSTALLED_APPS in settings file.
* After this apply migrations with "manage.py migrate oscar_accounts" command. This will create the appropriate database tables.
* Next use "manage.py oscar_accounts_init" command to create core accounts and account-types. The names of these accounts can be controlled using settings.
* To access accounts via Django Oscar dashboard, you need to update OSCAR_DASHBOARD_NAVIGATION list
from oscar.defaults import *
OSCAR_DASHBOARD_NAVIGATION.append(
{
'label': 'Accounts',
'icon': 'icon-globe',
'children': [
{
'label': 'Accounts',
'url_name': 'accounts-list',
},
{
'label': 'Transfers',
'url_name': 'transfers-list',
},
{
'label': 'Deferred income report',
'url_name': 'report-deferred-income',
},
{
'label': 'Profit/loss report',
'url_name': 'report-profit-loss',
},
]
})
Next, add the below url-pattern to your urls.py
from oscar_accounts.dashboard.app import application as accounts_app
urlpatterns = [
...
url(r'^dashboard/accounts/', include(accounts_app.urls)),
]
NOTE: To override templates, add an additional path(ACCOUNTS_TEMPLATE_DIR) to your TEMPLATE_DIRS
Integrating in Django Oscar Checkout Process
For checkout integration, you have to override PaymentDetailsView in checkout app
Step 1: Display the list of accounts for the user in final step(Payment details Page).
For this, override the get_context_data() method and filter active user accounts as below.
from oscar_accounts.models import Account
accounts = Account.active.filter(user=user, balance__gt=0)
Step 2: Override the "post" method to validate the selected account and render them again in the preview view (but as hidden).
Step 3: Override the handle_payment method of your checkout's PaymentDetailsView to transfer the amount(order total amount) from the user account to your account(Ex: Sales Account)
* This package provides an API to make transfers in facade module.
* If the transfer is invalid, an exception is raised. All these exceptions are subclasses of oscar_accounts.exceptions.AccountException. So we just need to handle this exception.
from oscar_accounts.models import Account
from oscar_accounts import facade, exceptions
source_account = user_selected_account
destination_account = Account.objects.get(name="Sales")
try:
transfer = facade.transfer(source_account,
destination_account,
order_total,
user=user
merchant_reference=order_number,
description="Redeemed to pay for order %s" % order_number)
except exceptions.AccountException, e:
raise PaymentError("Transfer Failed")
else:
# Add Payment source and Payment event
source_type, created = SourceType.objects.get_or_create(name="Accounts")
source = Source(source_type=source_type,
amount_allocated=order_total,
amount_debited=transfer.amount,
reference=transfer.reference)
self.add_payment_source(source)
self.add_payment_event("Transferred",
transfer.amount,
transfer.reference)
* If the transfer is successful, but something went wrong in placing the order(any exception occurs after post-payment), then you have to roll-back the previous transfer.
from oscar_accounts import facade
try:
self.place_order()
except Exception, e:
facade.reverse(transfer, user=user,
merchant_reference=order_number,
description="Payment Cancellation")
Note: Transfer operation is wrapped in its own db transaction to make sure that only complete transfers are written.