Add billing tab
authorSofia Papagiannaki <papagian@gmail.com>
Tue, 4 Sep 2012 09:23:49 +0000 (12:23 +0300)
committerSofia Papagiannaki <papagian@gmail.com>
Tue, 4 Sep 2012 09:23:49 +0000 (12:23 +0300)
snf-astakos-app/README
snf-astakos-app/astakos/im/api/__init__.py
snf-astakos-app/astakos/im/endpoints/aquarium/client.py [new file with mode: 0644]
snf-astakos-app/astakos/im/settings.py
snf-astakos-app/astakos/im/tasks.py
snf-astakos-app/astakos/im/templates/im/billing.html [new file with mode: 0644]
snf-astakos-app/astakos/im/urls.py
snf-astakos-app/astakos/im/views.py
snf-astakos-app/conf/20-snf-astakos-app-settings.conf
snf-astakos-app/setup.py

index 8f99c99..0a282a9 100644 (file)
@@ -80,6 +80,9 @@ ASTAKOS_EMAILCHANGE_ENABLED         False
 ASTAKOS_EMAILCHANGE_ACTIVATION_DAYS 10                                                                              Number of days that email change requests remain active
 ASTAKOS_LOGGING_LEVEL               INFO                                                                            Message logging severity
 ASTAKOS_QUOTA_HOLDER_URL            ''                                                                              The quota holder URI
+                                                                                                                    e.g. ``http://localhost:8080/api/quotaholder/v``
+AQUARIUM_URL                        ''                                                                              The billing (aquarium) URI
+                                                                                                                    e.g. ``http://localhost:8888/user``
 =================================== =============================================================================   ===========================================================================================
 
 Administrator functions
index 171e173..344883b 100644 (file)
@@ -174,6 +174,7 @@ def get_menu(request, with_extra_links=False, with_signout=True):
             l.append(dict(url=absolute(reverse('feedback')), name="Feedback"))
             l.append(dict(url=absolute(reverse('group_list')), name="Groups"))
             l.append(dict(url=absolute(reverse('resource_list')), name="Resources"))
+            l.append(dict(url=absolute(reverse('billing')), name="Billing"))
         if with_signout:
             l.append(dict(url=absolute(reverse('logout')), name="Sign out"))
 
diff --git a/snf-astakos-app/astakos/im/endpoints/aquarium/client.py b/snf-astakos-app/astakos/im/endpoints/aquarium/client.py
new file mode 100644 (file)
index 0000000..f0d5d11
--- /dev/null
@@ -0,0 +1,52 @@
+# Copyright 2011-2012 GRNET S.A. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or
+# without modification, are permitted provided that the following
+# conditions are met:
+#
+#   1. Redistributions of source code must retain the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer.
+#
+#   2. Redistributions in binary form must reproduce the above
+#      copyright notice, this list of conditions and the following
+#      disclaimer in the documentation and/or other materials
+#      provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and
+# documentation are those of the authors and should not be
+# interpreted as representing official policies, either expressed
+# or implied, of GRNET S.A.
+
+import requests
+
+from django.utils import simplejson as json
+
+from astakos.im.settings import AQUARIUM_URL
+
+class AquariumClient():
+    def get_billing(self, user, start, end):
+        if not AQUARIUM_URL:
+            return
+        
+        url = AQUARIUM_URL.rstrip('/')
+        url = '%s/%s/bill/%d/%d' % (url, user, start, end)
+        r = requests.get(url)
+        try:
+            return r.status_code, json.loads(r.text)
+        except ValueError:
+            pass
+        return r.status_code, None
\ No newline at end of file
index fe20aba..562c287 100644 (file)
@@ -99,4 +99,7 @@ from logging import INFO
 LOGGING_LEVEL = getattr(settings, 'ASTAKOS_LOGGING_LEVEL', INFO)
 
 # Set the quota holder component URI
-QUOTA_HOLDER_URL = getattr(settings, 'ASTAKOS_QUOTA_HOLDER_URL', '')
\ No newline at end of file
+QUOTA_HOLDER_URL = getattr(settings, 'ASTAKOS_QUOTA_HOLDER_URL', '')
+
+# Set the billing URI
+AQUARIUM_URL = getattr(settings, 'ASTAKOS_AQUARIUM_URL', '')
index ff31fef..f95ef7e 100644 (file)
@@ -37,9 +37,10 @@ from celery.schedules import crontab
 from functools import wraps
 
 from astakos.im.endpoints.quotaholder import send_quota
-from astakos.im.endpoints.aquarium.producer import (report_credits_event
-    , report_user_event
+from astakos.im.endpoints.aquarium.producer import (report_credits_event,
+    report_user_event
 )
+from astakos.im.endpoints.aquarium.client import AquariumClient
 
 import logging
 
@@ -48,7 +49,10 @@ logger = logging.getLogger(__name__)
 def log(func):
     @wraps(func)
     def wrapper(*args, **kwargs):
-        logger.info('Starting the %s' % func)
+        logger.info('Starting the %s with args=%s kwargs=%s' % (
+                func, args, kwargs
+            )
+        )
         return func(*args, **kwargs)
     return wrapper
 
@@ -63,3 +67,8 @@ def propagate_groupmembers_quota(group):
     if group.is_disabled:
         return
     send_quota(group.approved_members)
+
+@task
+@log
+def request_billing(user, start, end):
+    return AquariumClient().get_billing(user, start, end)
diff --git a/snf-astakos-app/astakos/im/templates/im/billing.html b/snf-astakos-app/astakos/im/templates/im/billing.html
new file mode 100644 (file)
index 0000000..bffd8e7
--- /dev/null
@@ -0,0 +1,9 @@
+{% extends "im/account_base.html" %}
+
+{% load filters %}
+
+{% block page.body %}
+    {% if data %}
+        {{ data }}
+    {% endif %}
+{% endblock %}
index dd619d0..f3331ee 100644 (file)
@@ -48,13 +48,13 @@ urlpatterns = patterns('astakos.im.views',
     url(r'^approval_terms/(?P<term_id>\d+)/?$', 'approval_terms'),
     url(r'^password/?$', 'change_password', {}, name='password_change'),
     url(r'^resources/?$', 'resource_list', {}, name='resource_list'),
+    url(r'^billing/?$', 'billing', {}, name='billing'),
     url(r'^group/add/(?P<kind_name>\w+)?$', 'group_add', {}, name='group_add'),
     url(r'^group/list/?$', 'group_list', {}, name='group_list'),
     url(r'^group/(?P<group_id>\d+)/?$', 'group_detail', {}, name='group_detail'),
     url(r'^group/search/?$', 'group_search', {}, name='group_search'),
     url(r'^group/(?P<group_id>\d+)/join/?$', 'group_join', {}, name='group_join'),
     url(r'^group/(?P<group_id>\d+)/leave/?$', 'group_leave', {}, name='group_leave'),
-    #url(r'^group/(?P<group_id>\d+)/request/approval/?$', 'group_approval_request', {}, name='group_approval_request'),
     url(r'^group/(?P<group_id>\d+)/(?P<user_id>\d+)/approve/?$', 'approve_member', {}, name='approve_member'),
     url(r'^group/(?P<group_id>\d+)/(?P<user_id>\d+)/disapprove/?$', 'disapprove_member', {}, name='disapprove_member'),
     url(r'^group/create/?$', 'group_create_list', {}, name='group_create_list'),
index 01aa9a7..9f0e35b 100644 (file)
@@ -32,6 +32,7 @@
 # or implied, of GRNET S.A.
 
 import logging
+import calendar
 
 from urllib import quote
 from functools import wraps
@@ -71,6 +72,7 @@ from astakos.im.functions import (send_feedback, SendMailError,
 from astakos.im.settings import (COOKIE_NAME, COOKIE_DOMAIN, SITENAME, LOGOUT_NEXT,
     LOGGING_LEVEL
 )
+from astakos.im.tasks import request_billing
 
 logger = logging.getLogger(__name__)
 
@@ -184,7 +186,6 @@ def invite(request, template_name='im/invitations.html', extra_context=None):
 
     * LOGIN_URL: login uri
     * ASTAKOS_DEFAULT_CONTACT_EMAIL: service support email
-    * ASTAKOS_DEFAULT_FROM_EMAIL: from email
     """
     status = None
     message = None
@@ -836,10 +837,32 @@ def resource_list(request):
         quota=request.user.quota
     )
     
-@signed_terms_required
-@login_required
 def group_create_list(request):
     return render_response(
         template='im/astakosgroup_create_list.html',
         context_instance=get_context(request),
-    )    
\ No newline at end of file
+    )
+
+@signed_terms_required
+@login_required
+def billing(request):
+    today = datetime.today()
+    month_last_day = calendar.monthrange(today.year, today.month)[1]
+    start = datetime(today.year, today.month, 1).strftime("%s")
+    end = datetime(today.year, today.month, month_last_day).strftime("%s")
+    r = request_billing.apply(args=(request.user.email,
+        int(start) * 1000,
+        int(end) * 1000)
+    )
+    data = None
+    try:
+        status, data = r.result
+        if status != 200:
+            messages.error(request, _('Service response status: %d' % status))
+    except:
+        messages.error(request, r.result)
+    return render_response(
+        template='im/billing.html',
+        context_instance=get_context(request),
+        data = data
+    )
\ No newline at end of file
index 6506337..ec51a18 100644 (file)
@@ -99,3 +99,9 @@
 # Set the astakos main functions logging severity (None to disable)
 #from logging import INFO
 #ASTAKOS_LOGGING_LEVEL = INFO
+
+# Set the quota holder component URI
+#ASTAKOS_QUOTA_HOLDER_URL = ''
+
+# Set the billing URI
+#ASTAKOS_AQUARIUM_URL = ''
\ No newline at end of file
index 11a9bcf..86b13be 100644 (file)
@@ -44,7 +44,6 @@ from distutils.util import convert_path
 from setuptools import setup, find_packages
 from astakos import get_version
 
-
 HERE = os.path.abspath(os.path.normpath(os.path.dirname(__file__)))
 try:
     # try to update the version file
@@ -82,7 +81,8 @@ INSTALL_REQUIRES = [
     'django-recaptcha',
     'django-ratelimit==0.1',
     'commissioning',
-    'celery'
+    'celery',
+    'requests',
 ]
 
 EXTRAS_REQUIRES = {