October feature list #226

Merged
tobru merged 36 commits from october into main 2025-10-22 13:43:34 +00:00
5 changed files with 87 additions and 12 deletions
Showing only changes of commit 6443582c0e - Show all commits

View file

@ -108,16 +108,19 @@ class OSBServiceInstanceView(OSBBasicAuthPermission, View):
if service in organization.limit_osb_services.all():
return JsonResponse({"message": "Service already enabled"}, status=200)
except Organization.DoesNotExist:
odoo_data = {
"company_name": organization_display_name,
"invoice_email": user.email,
}
with transaction.atomic():
try:
billing_entity = BillingEntity.create_from_data(
name=f"{organization_display_name} (Exoscale)",
odoo_data=odoo_data,
)
try:
with transaction.atomic():
if exoscale_origin.billing_entity:
billing_entity = exoscale_origin.billing_entity
else:
odoo_data = {
"company_name": organization_display_name,
"invoice_email": user.email,
}
billing_entity = BillingEntity.create_from_data(
name=f"{organization_display_name} (Exoscale)",
odoo_data=odoo_data,
)
organization = Organization(
name=organization_display_name,
billing_entity=billing_entity,
@ -126,8 +129,8 @@ class OSBServiceInstanceView(OSBBasicAuthPermission, View):
)
organization = Organization.create_organization(organization, user)
self._send_invitation_email(request, organization, user)
except Exception:
return JsonResponse({"error": "Internal server error"}, status=500)
except Exception:
return JsonResponse({"error": "Internal server error"}, status=500)
organization.limit_osb_services.add(service)
self._send_service_welcome_email(

View file

@ -0,0 +1,26 @@
# Generated by Django 5.2.7 on 2025-10-17 00:22
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("core", "0009_organization_limit_cloudproviders_and_more"),
]
operations = [
migrations.AddField(
model_name="organizationorigin",
name="billing_entity",
field=models.ForeignKey(
help_text="If set, this billing entity will be used on new organizations with this origin.",
null=True,
on_delete=django.db.models.deletion.PROTECT,
related_name="origins",
to="core.billingentity",
verbose_name="Billing entity",
),
),
]

View file

@ -355,6 +355,16 @@ class OrganizationOrigin(ServalaModelMixin, models.Model):
name = models.CharField(max_length=100, verbose_name=_("Name"))
description = models.TextField(blank=True, verbose_name=_("Description"))
billing_entity = models.ForeignKey(
to="BillingEntity",
on_delete=models.PROTECT,
related_name="origins",
verbose_name=_("Billing entity"),
help_text=_(
"If set, this billing entity will be used on new organizations with this origin."
),
null=True,
)
class Meta:
verbose_name = _("Organization origin")

View file

@ -3,6 +3,7 @@ import base64
import pytest
from servala.core.models import (
BillingEntity,
Organization,
OrganizationMembership,
OrganizationOrigin,
@ -21,6 +22,11 @@ def origin():
return OrganizationOrigin.objects.create(name="TESTORIGIN")
@pytest.fixture
def billing_entity():
return BillingEntity.objects.create(name="Test Entity")
@pytest.fixture
def organization(origin):
return Organization.objects.create(name="Test Org", origin=origin)

View file

@ -99,6 +99,36 @@ def test_successful_onboarding_new_organization(
assert "redis/offering/" in welcome_email.body
@pytest.mark.django_db
def test_new_organization_inherits_origin(
osb_client,
test_service,
test_service_offering,
valid_osb_payload,
exoscale_origin,
instance_id,
billing_entity,
):
valid_osb_payload["service_id"] = test_service.osb_service_id
valid_osb_payload["plan_id"] = test_service_offering.osb_plan_id
exoscale_origin.billing_entity = billing_entity
exoscale_origin.save()
response = osb_client.put(
f"/api/osb/v2/service_instances/{instance_id}",
data=json.dumps(valid_osb_payload),
content_type="application/json",
)
assert response.status_code == 201
response_data = json.loads(response.content)
assert response_data["message"] == "Successfully enabled service"
org = Organization.objects.get(osb_guid="test-org-guid-123")
assert org.name == "Test Organization Display"
assert org.billing_entity == exoscale_origin.billing_entity
@pytest.mark.django_db
def test_duplicate_organization_returns_existing(
osb_client,