Skip to content

Commit

Permalink
Merge branch 'dev-v2' into staging
Browse files Browse the repository at this point in the history
  • Loading branch information
jefmoura committed Mar 6, 2018
2 parents f4a2fe4 + a777364 commit 47506ab
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 21 deletions.
1 change: 1 addition & 0 deletions docker-compose-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@ services:
- CHARGEBEE_SITE_API_KEY=test_31lcdE7L3grqdkGcvy24ik3lmlJrnA0Ez
- CHARGEBEE_SITE=toladata-test
- TOLA_TRACK_SYNC_ENABLED=False
- [email protected]
50 changes: 42 additions & 8 deletions feed/tests/test_budgetview.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from decimal import Decimal

from django.test import TestCase
from rest_framework.test import APIRequestFactory
from rest_framework.reverse import reverse
Expand Down Expand Up @@ -76,9 +78,10 @@ def test_create_budget(self):
response = view(request)

self.assertEqual(response.status_code, 201)
self.assertEqual(response.data['proposed_value'],
self.assertEqual(Decimal(response.data['proposed_value']),
data['proposed_value'])
self.assertEqual(response.data['actual_value'], data['actual_value'])
self.assertEqual(Decimal(response.data['actual_value']),
data['actual_value'])
self.assertEqual(response.data['created_by'], user_url)

# Check WorkflowLevel2
Expand All @@ -101,9 +104,10 @@ def test_create_budget_without_wkfl2(self):
response = view(request)

self.assertEqual(response.status_code, 201)
self.assertEqual(response.data['proposed_value'],
self.assertEqual(Decimal(response.data['proposed_value']),
data['proposed_value'])
self.assertEqual(response.data['actual_value'], data['actual_value'])
self.assertEqual(Decimal(response.data['actual_value']),
data['actual_value'])
self.assertEqual(response.data['created_by'], user_url)


Expand All @@ -129,14 +133,42 @@ def test_update_budget(self):

budget = Budget.objects.get(pk=response.data['id'])
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['proposed_value'], budget.proposed_value)
self.assertEqual(response.data['actual_value'], budget.actual_value)
self.assertEqual(Decimal(response.data['proposed_value']),
budget.proposed_value)
self.assertEqual(Decimal(response.data['actual_value']),
budget.actual_value)

# Check WorkflowLevel2
wkfl2 = budget.workflowlevel2
self.assertEquals(wkfl2.total_estimated_budget, data['proposed_value'])
self.assertEquals(wkfl2.actual_cost, data['actual_value'])

def test_update_budget_without_actual_value(self):
wflvl1 = factories.WorkflowLevel1(
name='WorkflowLevel1', organization=self.tola_user.organization)
wflvl2 = factories.WorkflowLevel2(
name='WorkflowLevel2', actual_cost=100, total_estimated_budget=0,
workflowlevel1=wflvl1)
budget = factories.Budget(workflowlevel2=wflvl2,
proposed_value=None, actual_value=None)

data = {'proposed_value': 5678}
request = self.factory.post('/api/budget/', data)
request.user = self.tola_user.user
view = BudgetViewSet.as_view({'post': 'update'})
response = view(request, pk=budget.pk)

budget = Budget.objects.get(pk=response.data['id'])
self.assertEqual(response.status_code, 200)
self.assertEqual(Decimal(response.data['proposed_value']),
budget.proposed_value)
self.assertEqual(Decimal(response.data['actual_value']), 0)

# Check WorkflowLevel2
wkfl2 = budget.workflowlevel2
self.assertEquals(wkfl2.total_estimated_budget, data['proposed_value'])
self.assertEquals(wkfl2.actual_cost, 100)

def test_update_budget_without_wkfl2(self):
budget = factories.Budget()

Expand All @@ -149,8 +181,10 @@ def test_update_budget_without_wkfl2(self):

budget = Budget.objects.get(pk=response.data['id'])
self.assertEqual(response.status_code, 201)
self.assertEqual(response.data['proposed_value'], budget.proposed_value)
self.assertEqual(response.data['actual_value'], budget.actual_value)
self.assertEqual(Decimal(response.data['proposed_value']),
budget.proposed_value)
self.assertEqual(Decimal(response.data['actual_value']),
budget.actual_value)


class BudgetFilterViewTest(TestCase):
Expand Down
6 changes: 6 additions & 0 deletions tola/settings/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,9 @@
chargebee.configure(os.getenv('CHARGEBEE_SITE_API_KEY'), os.getenv('CHARGEBEE_SITE'))

########## END CHARGEBEE CONFIGURATION

########## EMAIL CONFIGURATION

DEFAULT_REPLY_TO = os.getenv('DEFAULT_REPLY_TO', '')

########## END EMAIL CONFIGURATION
36 changes: 36 additions & 0 deletions workflow/migrations/0018_auto_20180302_0814.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.3 on 2018-03-02 16:14
from __future__ import unicode_literals

from decimal import Decimal
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('workflow', '0017_auto_20180226_0031'),
]

operations = [
migrations.AlterField(
model_name='budget',
name='actual_value',
field=models.DecimalField(blank=True, decimal_places=2, default=Decimal('0.00'), help_text='Monetary value positive or negative', max_digits=12, verbose_name='Actual'),
),
migrations.AlterField(
model_name='budget',
name='proposed_value',
field=models.DecimalField(blank=True, decimal_places=2, default=Decimal('0.00'), help_text='Approximate value if not a monetary fund', max_digits=12, verbose_name='Budget'),
),
migrations.AlterField(
model_name='historicalbudget',
name='actual_value',
field=models.DecimalField(blank=True, decimal_places=2, default=Decimal('0.00'), help_text='Monetary value positive or negative', max_digits=12, verbose_name='Actual'),
),
migrations.AlterField(
model_name='historicalbudget',
name='proposed_value',
field=models.DecimalField(blank=True, decimal_places=2, default=Decimal('0.00'), help_text='Approximate value if not a monetary fund', max_digits=12, verbose_name='Budget'),
),
]
15 changes: 10 additions & 5 deletions workflow/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1341,12 +1341,12 @@ class Meta:

class Budget(models.Model):
contributor = models.CharField(max_length=135, blank=True, null=True, help_text="Source of budget fund")
account_code = models.CharField("Accounting Code",max_length=135, blank=True, null=True, help_text="Label or coded field")
cost_center = models.CharField("Cost Center",max_length=135, blank=True, null=True, help_text="Associate a cost with a type of expense")
donor_code = models.CharField("Donor Code",max_length=135, blank=True, null=True, help_text="Third Party coded field")
account_code = models.CharField("Accounting Code", max_length=135, blank=True, null=True, help_text="Label or coded field")
cost_center = models.CharField("Cost Center", max_length=135, blank=True, null=True, help_text="Associate a cost with a type of expense")
donor_code = models.CharField("Donor Code", max_length=135, blank=True, null=True, help_text="Third Party coded field")
description_of_contribution = models.CharField(max_length=255, blank=True, null=True, help_text="Purpose or use for funds")
proposed_value = models.IntegerField("Budget",default=0, blank=True, null=True, help_text="Approximate value if not a monetary fund")
actual_value = models.IntegerField("Actual", default=0, blank=True, null=True, help_text="Monetary value positive or negative")
proposed_value = models.DecimalField("Budget", decimal_places=2, max_digits=12, default=Decimal("0.00"), blank=True, help_text="Approximate value if not a monetary fund")
actual_value = models.DecimalField("Actual", decimal_places=2, max_digits=12, default=Decimal("0.00"), blank=True, help_text="Monetary value positive or negative")
workflowlevel2 = models.ForeignKey(WorkflowLevel2, blank=True, null=True, on_delete=models.SET_NULL, help_text="Releated workflow level 2")
local_currency = models.ForeignKey(Currency, blank=True, null=True, related_name="local", help_text="Primary Currency")
donor_currency = models.ForeignKey(Currency, blank=True, null=True, related_name="donor", help_text="Secondary Currency")
Expand All @@ -1360,6 +1360,11 @@ def save(self, *args, **kwargs):
self.create_date = timezone.now()
self.edit_date = timezone.now()

if self.proposed_value is None:
self.proposed_value = Decimal("0.00")
if self.actual_value is None:
self.actual_value = Decimal("0.00")

if self.workflowlevel2:
wflvl2 = self.workflowlevel2
try:
Expand Down
29 changes: 25 additions & 4 deletions workflow/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
except ImportError:
pass
from django.conf import settings
from django.core.mail import EmailMessage
from django.contrib.auth.models import Group
from django.db.models import signals
from django.dispatch import receiver
Expand Down Expand Up @@ -107,8 +108,18 @@ def check_seats_save_team(sender, instance, **kwargs):
if user_addon:
available_seats = user_addon.quantity
if available_seats < org.chargebee_used_seats:
# TODO: Notify the Org admin
pass
user_email = instance.workflow_user.user.email
email = EmailMessage(
subject='Exceeded the number of editors',
body='The number of editors has exceeded the amount of '
'users set in your Subscription. Please check it out!'
'\nCurrent amount of editors: {}.\nSelected amount '
'of editors: {}.'.format(
org.chargebee_used_seats, available_seats),
to=[user_email],
reply_to=[settings.DEFAULT_REPLY_TO],
)
email.send()


@receiver(signals.pre_delete, sender=WorkflowTeam)
Expand Down Expand Up @@ -189,8 +200,18 @@ def check_seats_save_user_groups(sender, instance, **kwargs):
if user_addon:
available_seats = user_addon.quantity
if available_seats < org.chargebee_used_seats:
# TODO: Notify the Org admin
pass
user_email = instance.email
email = EmailMessage(
subject='Exceeded the number of editors',
body='The number of editors has exceeded the amount of '
'users set in your Subscription. Please check it '
'out!\nCurrent amount of editors: {}.\nSelected '
'amount of editors: {}.'.format(
org.chargebee_used_seats, available_seats),
to=[user_email],
reply_to=[settings.DEFAULT_REPLY_TO],
)
email.send()


# ORGANIZATION SIGNALS
Expand Down
63 changes: 59 additions & 4 deletions workflow/tests/test_signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from chargebee import Addon, Subscription
except ImportError:
pass
from django.core import mail
from django.test import TestCase, override_settings, tag
from mock import Mock, patch

Expand Down Expand Up @@ -109,7 +110,7 @@ def __init__(self, values):

addon = Addon(values)
addon.id = 'user'
addon.quantity = 0
addon.quantity = 1
self.subscription.addons = [addon]

def setUp(self):
Expand Down Expand Up @@ -216,6 +217,34 @@ def test_check_seats_save_team_org_admin(self):
organization = Organization.objects.get(pk=self.org.id)
self.assertEqual(organization.chargebee_used_seats, 1)

@override_settings(DEFAULT_REPLY_TO='[email protected]')
def test_check_seats_save_team_exceed_notify(self):
self.tola_user.user.groups.add(self.group_org_admin)
self.tola_user.user.save()
self.org = Organization.objects.get(pk=self.org.id)
user = factories.User(first_name='John', last_name='Lennon')
tolauser = factories.TolaUser(user=user, organization=self.org)

external_response = self.ExternalResponse(None)
Subscription.retrieve = Mock(return_value=external_response)
wflvl1 = factories.WorkflowLevel1(name='WorkflowLevel1')
factories.WorkflowTeam(workflow_user=tolauser,
workflowlevel1=wflvl1,
role=self.group_program_admin)

# It should notify the OrgAdmin
organization = Organization.objects.get(pk=self.org.id)
self.assertEqual(organization.chargebee_used_seats, 2)
self.assertEqual(len(mail.outbox), 1)
self.assertIn('Exceeded the number of editors', mail.outbox[0].subject)
self.assertEqual(mail.outbox[0].to, [user.email])
self.assertEqual(mail.outbox[0].reply_to, ['[email protected]'])
self.assertEqual(mail.outbox[0].body,
'The number of editors has exceeded the amount of '
'users set in your Subscription. Please check it '
'out!\nCurrent amount of editors: 2.\nSelected '
'amount of editors: 1.')


class CheckSeatsDeleteWFTeamsTest(TestCase):
class ExternalResponse:
Expand All @@ -225,7 +254,7 @@ def __init__(self, values):

addon = Addon(values)
addon.id = 'user'
addon.quantity = 0
addon.quantity = 1
self.subscription.addons = [addon]

def setUp(self):
Expand All @@ -251,7 +280,7 @@ def test_check_seats_delete_team_decrease(self):
organization = Organization.objects.get(pk=self.org.id)
self.assertEqual(organization.chargebee_used_seats, 0)

def test_check_seats_save_team_not_decrease(self):
def test_check_seats_delete_team_not_decrease(self):
external_response = self.ExternalResponse(None)
Subscription.retrieve = Mock(return_value=external_response)
wflvl1_1 = factories.WorkflowLevel1(name='WorkflowLevel1_1')
Expand Down Expand Up @@ -310,7 +339,7 @@ def __init__(self, values):

addon = Addon(values)
addon.id = 'user'
addon.quantity = 0
addon.quantity = 1
self.subscription.addons = [addon]

def setUp(self):
Expand Down Expand Up @@ -378,6 +407,32 @@ def test_check_seats_save_user_groups_demo(self, mock_tsync):
organization = Organization.objects.get(pk=self.org.id)
self.assertEqual(organization.chargebee_used_seats, 0)

@override_settings(DEFAULT_REPLY_TO='[email protected]')
def test_check_seats_save_user_groups_exceed_notify(self):
external_response = self.ExternalResponse(None)
Subscription.retrieve = Mock(return_value=external_response)
self.tola_user.user.groups.add(self.group_org_admin)
self.tola_user.user.save()

self.org = Organization.objects.get(pk=self.org.id)
user = factories.User(first_name='John', last_name='Lennon')
tolauser = factories.TolaUser(user=user, organization=self.org)
tolauser.user.groups.add(self.group_org_admin)
tolauser.user.save()

# It should notify the OrgAdmin
organization = Organization.objects.get(pk=self.org.id)
self.assertEqual(organization.chargebee_used_seats, 2)
self.assertEqual(len(mail.outbox), 1)
self.assertIn('Exceeded the number of editors', mail.outbox[0].subject)
self.assertEqual(mail.outbox[0].to, [user.email])
self.assertEqual(mail.outbox[0].reply_to, ['[email protected]'])
self.assertEqual(mail.outbox[0].body,
'The number of editors has exceeded the amount of '
'users set in your Subscription. Please check it '
'out!\nCurrent amount of editors: 2.\nSelected '
'amount of editors: 1.')


class SignalSyncTrackTest(TestCase):
def setUp(self):
Expand Down

0 comments on commit 47506ab

Please sign in to comment.