Permalink
Browse files

Merge pull request #13 from deshipu/master

Basic report for the ventures
  • Loading branch information...
2 parents e852b76 + 909add2 commit d80285ff915a9c377d9732444fec7a19260f60c7 @wmatyskiewicz wmatyskiewicz committed May 9, 2013
@@ -6,6 +6,7 @@
from __future__ import unicode_literals
import collections
+import datetime
from django import forms
from django.utils.translation import ugettext_lazy as _
@@ -147,3 +148,21 @@ def clean(self):
can_delete=True,
)
+
+class DateRangeForm(forms.Form):
+ start = forms.DateField(
+ widget=DateWidget(
+ attrs={'class': 'input-small'},
+ ),
+ label='Start date',
+ initial=lambda: datetime.date.today() - datetime.timedelta(days=30),
+ )
+ end = forms.DateField(
+ widget=DateWidget(
+ attrs={'class': 'input-small'},
+ ),
+ label='End date',
+ initial=datetime.date.today,
+ )
+
+
@@ -5,6 +5,9 @@
from __future__ import print_function
from __future__ import unicode_literals
+import decimal
+from dateutil import rrule
+
from django.db import models as db
from django.utils.translation import ugettext_lazy as _
@@ -75,6 +78,52 @@ class MPTTMeta:
def __unicode__(self):
return self.name
+ def _by_venture(self, query, descendants):
+ if descendants:
+ ventures = self.get_descendants(include_self=True)
+ return query.filter(pricing_venture__in=ventures)
+ return query.filter(pricing_venture=self)
+
+ def get_assets_count_price(self, start, end, descendants=False):
+ days = (end - start).days + 1
+ query = DailyDevice.objects.all()
+ query = self._by_venture(query, descendants)
+ query = query.filter(date__gte=start, date__lte=end)
+ price = query.aggregate(db.Sum('price'))['price__sum'] or 0
+ count = query.count()
+ return count / days, price / days
+
+ def get_usages_count_price(self, start, end, type_, descendants=False):
+ count = 0
+ price = decimal.Decimal('0')
+ query = DailyUsage.objects.filter(type=type_)
+ query = self._by_venture(query, descendants)
+ for day in rrule.rrule(rrule.DAILY, dtstart=start, until=end):
+ query = query.filter(date=day)
+ daily_count = query.aggregate(db.Sum('value'))['value__sum'] or 0
+ count += daily_count
+ if count:
+ try:
+ daily_price = type_.get_price_at(day)
+ except (
+ UsagePrice.DoesNotExist,
+ UsagePrice.MultipleObjectsReturned,
+ ):
+ price = None
+ else:
+ if price is not None:
+ price += decimal.Decimal(daily_count) * daily_price
+ return count, price
+
+ def get_extra_costs(self, start, end, type_, descendants=False):
+ price = decimal.Decimal('0')
+ query = ExtraCost.objects.filter(type=type_)
+ query = self._by_venture(query, descendants)
+ for day in rrule.rrule(rrule.DAILY, dtstart=start, until=end):
+ query = query.filter(start__lte=day, end__gte=day)
+ price += query.aggregate(db.Sum('price'))['price__sum'] or 0
+ return price
+
class DailyPart(db.Model):
date = db.DateField()
@@ -157,6 +206,9 @@ class Meta:
def __unicode__(self):
return self.name
+ def get_price_at(self, date):
+ return self.usageprice_set.get(start__lte=date, end__gte=date).price
+
class UsagePrice(db.Model):
type = db.ForeignKey(UsageType, verbose_name=_("type"))
@@ -222,6 +274,9 @@ class Meta:
def __unicode__(self):
return self.name
+ def get_cost_at(self, date):
+ return 1 # XXX
+
class ExtraCost(db.Model):
start = db.DateField()
@@ -1,9 +1,64 @@
-{% extends "ui/base.html" %}
+<!DOCTYPE html>
{% load url from future %}
+{% load icons %}
{% load bob %}
-{% block sidebar %}
-{% if sidebar_items %}
-{% sidebar_menu sidebar_items sidebar_selected %}
-{% endif %}
+<html><head>
+<meta charset="utf-8">
+<title>{% block title %}{% block titlesection %}{% block titlesubsection %}{% endblock %}{{ section.title }}{% endblock %} - Ralph Pricing{% endblock %}</title>
+<link rel="stylesheet" href="{{ STATIC_URL }}bootstrap/css/bootstrap.min.css">
+<link rel="stylesheet" href="{{ STATIC_URL }}fugue-icons.css">
+<link rel="stylesheet" href="{{ STATIC_URL }}ui/custom.css">
+<link rel="stylesheet" href="{{ STATIC_URL }}ui/datepicker.css">
+{% block extra_headers %}{% endblock %}
+</head><body>
+<div class="container-fluid browser-min-width">
+ <div class="row-fluid"><div class="span12">
+ {% block header %}
+ <p></p>
+ {% main_menu mainmenu_items section title="Ralph Pricing" search=search_url %}
+ {% endblock %}
+ </div>
+ {% if messages %}
+ <div class="row-fluid"><div class="span12 alerts">
+ {% block alerts %}
+ {% for message in messages %}
+ <div class="alert alert-{{ message.tags }} fade in">
+ <a class="close" data-dismiss="alert" href="#">&times;</a>
+ <p>{{ message.tags|alert_icon }} {{ message }}</p>
+ </div>
+ {% endfor %}
+ {% endblock %}
+ </div></div>
+ {% endif %}
+ {% block contentarea %}
+ <div class="row-fluid main-body"><div class="span2">
+ {% block sidebar %}
+ {% sidebar_menu sidebar_items sidebar_selected %}
+ {% endblock %}
+ </div><div class="span10">
+ {% block breadcrumbs %}{% endblock %}
+ {% block tabs %}{% endblock %}
+ <div class="row-fluid">
+ {% block content %}{% endblock %}
+ </div>
+ </div></div>
+ {% endblock contentarea %}
+ <div class="row-fluid"><div class="span12">
+ {% block footer %}
+ <p></p>
+ {% main_menu footer_items section white=1 %}
+ {% endblock %}
+ </div>
+</div>
+{% block scripts %}
+<script src="{{ STATIC_URL }}jquery-1.7.2.min.js"></script>
+<script src="{{ STATIC_URL }}bootstrap/js/bootstrap.min.js"></script>
+<script src="{{ STATIC_URL }}bootstrap/js/bob.js"></script>
+<script src="{{ STATIC_URL }}bootstrap-datepicker.js"></script>
+<script src="{{ STATIC_URL }}mustache.js"></script>
+<script src="{{ STATIC_URL }}ui/main.js"></script>
{% endblock %}
+</body></html>
+<!--STATS-->
+
@@ -0,0 +1,48 @@
+{% extends "ralph_pricing/base.html" %}
+{% load url from future %}
+{% load icons %}
+{% load formats %}
+{% load bob %}
+
+{% block contentarea %}
+<div class="row-fluid main-body"><div class="span12">
+<form class="form form-inline daterange-form">
+<div class="form-actions">
+ {% for f in form %}
+ <div style="display:inline-block; vertical-align:top" class="control-group {% if f.errors %}error{% endif %}" >
+ {{ f }}
+ {% if f.errors %}
+ <span class="help-block">
+ {% for e in f.errors %}{{ e }}{% endfor %}
+ </span>
+ {% endif %}
+ </div>
+ {% endfor %}
+ <button type="submit" class="btn">{% spaceless %}
+ {% icon 'fugue-calendar-search-result' %}&nbsp;Update
+ {% endspaceless %}</button>
+ <button type="submit" class="btn pull-right" name="format" value="csv">{% spaceless %}
+ {% icon 'fugue-document-excel-csv' %}&nbsp;Download CSV
+ {% endspaceless %}</button>
+</div>
+</form>
+</div>
+
+<table class="table table-striped table-bordered table-condensed">
+ <tr>
+ {% for column in header %}
+ <th>{{ column }}</th>
+ {% endfor %}
+ </tr>
+ {% for row in data %}
+ <tr>
+ {% for value in row %}
+ <td
+ {% if forloop.counter > 3 %}style="text-align:right"{% endif %}
+ >{{ value }}</td>
+ {% endfor %}
+ </tr>
+ {% endfor %}
+</table>
+</div></div>
+{% endblock contentarea %}
@@ -6,6 +6,7 @@
from __future__ import unicode_literals
import datetime
+import decimal
from django.test import TestCase
@@ -95,3 +96,105 @@ def test_extra_cost_models(self):
self.assertEquals(cost.price, 3)
self.assertEquals(cost.pricing_venture, venture)
+class TestPrices(TestCase):
+ def test_asset_count_price(self):
+ day = datetime.date(2013, 4, 25)
+ venture = models.Venture(venture_id=3)
+ venture.save()
+ device = models.Device(
+ device_id=3,
+ asset_id=5,
+ )
+ device.save()
+ daily = models.DailyDevice(
+ pricing_device=device,
+ date=day,
+ name='ziew',
+ price='1337',
+ pricing_venture=venture,
+ )
+ daily.save()
+ subventure = models.Venture(venture_id=2, parent=venture)
+ subventure.save()
+ other_device = models.Device(
+ device_id=2,
+ asset_id=3,
+ )
+ other_device.save()
+ other_daily = models.DailyDevice(
+ pricing_device=other_device,
+ date=day,
+ name='ziew',
+ price='833833',
+ pricing_venture=subventure,
+ )
+ other_daily.save()
+ count, price = venture.get_assets_count_price(day, day)
+ self.assertEquals(count, 1)
+ self.assertEquals(price, decimal.Decimal('1337'))
+ count, price = venture.get_assets_count_price(day, day, True)
+ self.assertEquals(count, 2)
+ self.assertEquals(price, decimal.Decimal('835170'))
+
+ def test_usages_count_price(self):
+ day = datetime.date(2013, 4, 25)
+ venture = models.Venture(venture_id=3)
+ venture.save()
+ usage_type = models.UsageType(name='waciki')
+ usage_type.save()
+ daily_usage = models.DailyUsage(
+ type=usage_type,
+ value=32,
+ date=day,
+ pricing_venture=venture,
+ )
+ daily_usage.save()
+ other_day = datetime.date(2013, 4, 24)
+ daily_usage = models.DailyUsage(
+ type=usage_type,
+ value=32,
+ date=other_day,
+ pricing_venture=venture,
+ )
+ daily_usage.save()
+ usage_price = models.UsagePrice(
+ start=day,
+ end=day,
+ price=4,
+ type=usage_type,
+ )
+ usage_price.save()
+ count, price = venture.get_usages_count_price(day, day, usage_type)
+ self.assertEquals(count, 32)
+ self.assertEquals(price, decimal.Decimal('128'))
+ day = datetime.date(2013, 4, 26)
+ count, price = venture.get_usages_count_price(day, day, usage_type)
+ self.assertEquals(count, 0)
+ self.assertEquals(price, decimal.Decimal('0'))
+ day = datetime.date(2013, 4, 24)
+ count, price = venture.get_usages_count_price(day, day, usage_type)
+ self.assertEquals(count, 32)
+ self.assertIsNone(price)
+
+ def test_extra_costs(self):
+ day = datetime.date(2013, 4, 25)
+ venture = models.Venture(venture_id=3)
+ venture.save()
+ extra_cost_type = models.ExtraCostType(name='waciki')
+ extra_cost_type.save()
+ extra_cost = models.ExtraCost(
+ pricing_venture=venture,
+ start=day,
+ end=day,
+ type=extra_cost_type,
+ price='65535',
+ )
+ extra_cost.save()
+ price = venture.get_extra_costs(day, day, extra_cost_type)
+ self.assertEqual(price, decimal.Decimal('65535'))
+ price = venture.get_extra_costs(
+ datetime.date(2013, 4, 24),
+ datetime.date(2013, 4, 24),
+ extra_cost_type,
+ )
+ self.assertEqual(price, decimal.Decimal('0'))
Oops, something went wrong. Retry.

0 comments on commit d80285f

Please sign in to comment.