Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provisioning #1463

Open
wants to merge 21 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e7ad048
Update actions.py
tommygonzaleza Aug 20, 2024
b5d3767
Update actions.py
tommygonzaleza Aug 20, 2024
1b63ada
Merge pull request #1442 from breatheco-de/development
tommygonzaleza Aug 21, 2024
306ac39
form entry bugserializer not maps the custom_fields keys from IDS to …
alesanchezr Aug 23, 2024
916c02e
Merge pull request #1445 from breatheco-de/development
tommygonzaleza Aug 27, 2024
9e3dfe4
fix task notifications
jefer94 Aug 29, 2024
bfded3f
update deps
jefer94 Aug 29, 2024
38496f1
revert dep versions
jefer94 Aug 29, 2024
3f5e15f
Update create_academy_roles.py
tommygonzaleza Aug 29, 2024
e12ebe7
Merge pull request #1448 from jefer94/fix/task-notifications
tommygonzaleza Sep 2, 2024
b80a475
Merge pull request #1453 from breatheco-de/development
tommygonzaleza Sep 5, 2024
42f3c91
Update set_permissions.py
tommygonzaleza Sep 6, 2024
6a4d279
Merge pull request #1455 from breatheco-de/development
tommygonzaleza Sep 9, 2024
7620a34
Merge pull request #1462 from breatheco-de/development
tommygonzaleza Sep 18, 2024
d821e08
fix tests and an undefined variable error
jefer94 Sep 19, 2024
b153ee8
add an error when all installments were paid
jefer94 Sep 19, 2024
6aea26d
fix an error that cause that an renewed financing was showed as error
jefer94 Sep 19, 2024
b87e5f0
reset status message if an error is resolved
jefer94 Sep 19, 2024
7a989f6
Create base_provisioning.html
JennGuz Sep 19, 2024
05cb123
Update choose_vendor.html
JennGuz Sep 19, 2024
093dc10
Add files via upload
JennGuz Sep 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 72 additions & 4 deletions breathecode/assignments/tests/urls/tests_task_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,13 +375,13 @@ def test_task_id__put__with_one_task__with_revision_status(self):
@patch("breathecode.assignments.tasks.teacher_task_notification", MagicMock())
@patch("django.db.models.signals.pre_delete.send_robust", MagicMock(return_value=None))
@patch("breathecode.admissions.signals.student_edu_status_updated.send_robust", MagicMock(return_value=None))
def test_task_id__put__with_one_task__with_revision_status__teacher_auth(self):
def test_task_id__put__with_one_task__with_revision_status__teacher_auth__good_statuses(self):
from breathecode.assignments.tasks import student_task_notification, teacher_task_notification

statuses = ["PENDING", "APPROVED", "REJECTED", "IGNORED"]
for index in range(0, 4):
statuses = ["PENDING", "APPROVED", "REJECTED"]
for index in range(0, 3):
current_status = statuses[index]
next_status = statuses[index - 1 if index > 0 else 3]
next_status = statuses[index - 1 if index > 0 else 2]
task = {"revision_status": current_status, "user_id": (index * 2) + 1, "task_status": "DONE"}
cohort_users = [
{
Expand Down Expand Up @@ -438,6 +438,74 @@ def test_task_id__put__with_one_task__with_revision_status__teacher_auth(self):
student_task_notification.delay.call_args_list = []
activity_tasks.add_activity.delay.call_args_list = []

@patch("breathecode.assignments.tasks.student_task_notification", MagicMock())
@patch("breathecode.assignments.tasks.teacher_task_notification", MagicMock())
@patch("django.db.models.signals.pre_delete.send_robust", MagicMock(return_value=None))
@patch("breathecode.admissions.signals.student_edu_status_updated.send_robust", MagicMock(return_value=None))
def test_task_id__put__with_one_task__with_revision_status__teacher_auth__bad_statuses(self):
from breathecode.assignments.tasks import student_task_notification, teacher_task_notification

another_statuses = ["PENDING", "APPROVED", "REJECTED"]
statuses = ["IGNORED"]
statuses = ["PENDING", "APPROVED", "REJECTED"]
for index in range(0, 3):
current_status = statuses[index]
next_status = "IGNORED"
task = {"revision_status": current_status, "user_id": (index * 2) + 1, "task_status": "DONE"}
cohort_users = [
{
"role": "STUDENT",
"user_id": (index * 2) + 1,
},
{
"role": "TEACHER",
"user_id": (index * 2) + 2,
},
]
model = self.bc.database.create(user=2, task=task, cohort=1, cohort_user=cohort_users)
model2 = self.bc.database.create(cohort=1)
self.bc.request.authenticate(model.user[1])

url = reverse_lazy("assignments:task_id", kwargs={"task_id": index + 1})
data = {
"title": "They killed kenny",
"revision_status": next_status,
}
start = self.bc.datetime.now()
response = self.client.put(url, data, format="json")
end = self.bc.datetime.now()

json = response.json()
updated_at = self.bc.datetime.from_iso_string(json["updated_at"])
self.bc.check.datetime_in_range(start, end, updated_at)

del json["updated_at"]

expected = put_serializer(self, model.task, data=data)

self.assertEqual(json, expected)
self.assertEqual(response.status_code, status.HTTP_200_OK)

self.assertEqual(self.bc.database.list_of("assignments.Task"), [task_row(self, model.task, data=data)])
self.assertEqual(student_task_notification.delay.call_args_list, [])
self.assertEqual(teacher_task_notification.delay.call_args_list, [])

self.bc.check.calls(
activity_tasks.add_activity.delay.call_args_list,
[
call(
(index * 2) + 2,
"assignment_review_status_updated",
related_type="assignments.Task",
related_id=index + 1,
),
],
)

# teardown
self.bc.database.delete("assignments.Task")
activity_tasks.add_activity.delay.call_args_list = []

@patch("breathecode.assignments.tasks.student_task_notification", MagicMock())
@patch("breathecode.assignments.tasks.teacher_task_notification", MagicMock())
@patch("django.db.models.signals.pre_delete.send_robust", MagicMock(return_value=None))
Expand Down
6 changes: 3 additions & 3 deletions breathecode/assignments/tests/urls/tests_user_me_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,10 +629,10 @@ def test__put__with_task__one_item_in_body__passing_revision_status(self):
@patch("django.db.models.signals.pre_delete.send_robust", MagicMock(return_value=None))
@patch("breathecode.admissions.signals.student_edu_status_updated.send_robust", MagicMock(return_value=None))
def test__put__with_task__one_item_in_body__passing_revision_status__teacher_token(self):
statuses = ["APPROVED", "REJECTED", "IGNORED"]
for index in range(0, 3):
statuses = ["APPROVED", "REJECTED"]
for index in range(0, 2):
current_status = statuses[index]
next_status = statuses[index - 1 if index > 0 else 2]
next_status = statuses[index - 1 if index > 0 else 1]
task = {"revision_status": current_status, "task_status": "DONE"}
cohort_users = [
{
Expand Down
5 changes: 3 additions & 2 deletions breathecode/assignments/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import hashlib
import logging
import os
from slugify import slugify

from adrf.views import APIView
from asgiref.sync import sync_to_async
from circuitbreaker import CircuitBreakerError
Expand All @@ -15,6 +15,7 @@
from rest_framework.decorators import api_view
from rest_framework.exceptions import PermissionDenied
from rest_framework.response import Response
from slugify import slugify

import breathecode.activity.tasks as tasks_activity
import breathecode.assignments.tasks as tasks
Expand Down Expand Up @@ -749,7 +750,7 @@ def update(_req, data, _id=None, only_validate=True):
if serializer.is_valid():
if not only_validate:
serializer.save()
if _req.user.id != item.user.id:
if _req.user.id != item.user.id and item.revision_status != "IGNORED":
tasks.student_task_notification.delay(item.id)
return status.HTTP_200_OK, serializer.data
return status.HTTP_400_BAD_REQUEST, serializer.errors
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
"slug": "crud_subscription",
"description": "Create, update or delete subscriptions and plan financings of other users",
},
{"slug": "upload_assignment_telemetry", "description": "Allow upload the user's telemetry in a LearnPack assignment"},
]

ROLES = [
Expand Down Expand Up @@ -217,6 +218,7 @@
"read_activity",
"read_technology",
"read_academyservice",
"upload_assignment_telemetry"
],
},
{
Expand Down Expand Up @@ -300,6 +302,7 @@
"read_cohort_log",
"read_service",
"read_academyservice",
"upload_assignment_telemetry"
],
},
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@

GROUPS = [
{"name": "Admin", "permissions": [x["codename"] for x in PERMISSIONS], "inherit": []},
{"name": "Default", "permissions": ["get_my_profile", "create_my_profile", "update_my_profile"], "inherit": []},
{"name": "Default", "permissions": ["get_my_profile", "create_my_profile", "update_my_profile", "upload_assignment_telemetry"], "inherit": []},
{
"name": "Student",
"permissions": [
Expand Down
2 changes: 1 addition & 1 deletion breathecode/cypress/tests/urls/tests_load_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ def test_load_roles__check_the_capabilities(self):

for capability in CAPABILITIES:
self.assertRegex(capability["slug"], r"^[a-z_]+$")
self.assertRegex(capability["description"], r'^[a-zA-Z,. _()"]+$')
self.assertRegex(capability["description"], r'^[a-zA-Z,. _()"\']+$')
self.assertEqual(len(capability), 2)

def test_load_roles__check_the_roles(self):
Expand Down
27 changes: 26 additions & 1 deletion breathecode/marketing/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from breathecode.admissions.models import Academy, Cohort
from breathecode.monitoring.actions import test_link
from breathecode.services.activecampaign.client import acp_ids
from breathecode.utils import serpy
from breathecode.utils.integer_to_base import to_base
from capyc.rest_framework.exceptions import ValidationException
Expand Down Expand Up @@ -311,7 +312,6 @@ class FormEntryBigSerializer(serpy.Serializer):
utm_placement = serpy.Field()
utm_term = serpy.Field()
utm_plan = serpy.Field()
custom_fields = serpy.Field()
referral_key = serpy.Field()
tags = serpy.Field()
automations = serpy.Field()
Expand Down Expand Up @@ -341,6 +341,7 @@ class FormEntryBigSerializer(serpy.Serializer):
academy = AcademySmallSerializer(required=False)
lead_generation_app = LeadgenAppSmallSerializer(required=False)
user = UserSmallSerializer(required=False)
custom_fields = serpy.MethodField(required=False)

def get_tag_objects(self, obj):
tag_ids = []
Expand All @@ -358,6 +359,30 @@ def get_automation_objects(self, obj):
automations = Automation.objects.filter(slug__in=automation_ids, ac_academy__academy=obj.calculate_academy())
return AutomationSmallSerializer(automations, many=True).data

def get_custom_fields(self, obj):

if not isinstance(obj.custom_fields, dict):
return obj.custom_fields

def convert_dict(input_dict, mapping_dict):
print(input_dict, mapping_dict)
# Create an inverse mapping dictionary from the deal_custom_fields
inverse_mapping = {v: k for k, v in mapping_dict.items()}

# Create a new dictionary with the converted keys
converted_dict = {}
for key, value in input_dict.items():
if key in inverse_mapping:
new_key = inverse_mapping[key]
converted_dict[new_key] = value
else:
converted_dict[key] = value

return converted_dict

out = convert_dict(obj.custom_fields, acp_ids["deal"])
return out


class GetAcademySmallSerializer(serpy.Serializer):
id = serpy.Field()
Expand Down
23 changes: 18 additions & 5 deletions breathecode/payments/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,13 @@ def alert_payment_issue(message: str, button: str) -> None:
academy=subscription.academy,
)

bag.delete()
if bag:
bag.delete()

subscription.status = "PAYMENT_ISSUE"
subscription.save()

bag = None
client = None
if IS_DJANGO_REDIS:
client = get_redis_connection("default")
Expand Down Expand Up @@ -375,8 +377,10 @@ def alert_payment_issue(message: str, button: str) -> None:
subscription.valid_until += delta

subscription.invoices.add(invoice)

subscription.status = "ACTIVE"
subscription.status_message = None
subscription.save()

value = invoice.currency.format_price(invoice.amount)

subject = translation(
Expand Down Expand Up @@ -462,11 +466,13 @@ def alert_payment_issue(message: str, button: str) -> None:
academy=plan_financing.academy,
)

bag.delete()
if bag:
bag.delete()

plan_financing.status = "PAYMENT_ISSUE"
plan_financing.save()

bag = None
client = None
if IS_DJANGO_REDIS:
client = get_redis_connection("default")
Expand Down Expand Up @@ -568,6 +574,9 @@ def alert_payment_issue(message: str, button: str) -> None:
remaining_installments -= 1
plan_financing.valid_until = utc_now + relativedelta(months=remaining_installments)

elif remaining_installments > 0:
remaining_installments -= 1

plan_financing.invoices.add(invoice)

value = invoice.currency.format_price(invoice.amount)
Expand Down Expand Up @@ -600,10 +609,14 @@ def alert_payment_issue(message: str, button: str) -> None:
delta += relativedelta(months=1)

plan_financing.next_payment_at += delta
plan_financing.status = "ACTIVE" if remaining_installments > 0 else "FULLY_PAID"
plan_financing.status_message = None
plan_financing.save()

bag.was_delivered = True
bag.save()
# if this charge but the client paid all its installments, there hasn't been a new bag created
if bag:
bag.was_delivered = True
bag.save()

renew_plan_financing_consumables.delay(plan_financing.id)

Expand Down
Loading
Loading