parent
819e13481e
commit
6443582c0e
5 changed files with 87 additions and 12 deletions
|
|
@ -108,12 +108,15 @@ class OSBServiceInstanceView(OSBBasicAuthPermission, View):
|
||||||
if service in organization.limit_osb_services.all():
|
if service in organization.limit_osb_services.all():
|
||||||
return JsonResponse({"message": "Service already enabled"}, status=200)
|
return JsonResponse({"message": "Service already enabled"}, status=200)
|
||||||
except Organization.DoesNotExist:
|
except Organization.DoesNotExist:
|
||||||
|
try:
|
||||||
|
with transaction.atomic():
|
||||||
|
if exoscale_origin.billing_entity:
|
||||||
|
billing_entity = exoscale_origin.billing_entity
|
||||||
|
else:
|
||||||
odoo_data = {
|
odoo_data = {
|
||||||
"company_name": organization_display_name,
|
"company_name": organization_display_name,
|
||||||
"invoice_email": user.email,
|
"invoice_email": user.email,
|
||||||
}
|
}
|
||||||
with transaction.atomic():
|
|
||||||
try:
|
|
||||||
billing_entity = BillingEntity.create_from_data(
|
billing_entity = BillingEntity.create_from_data(
|
||||||
name=f"{organization_display_name} (Exoscale)",
|
name=f"{organization_display_name} (Exoscale)",
|
||||||
odoo_data=odoo_data,
|
odoo_data=odoo_data,
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -355,6 +355,16 @@ class OrganizationOrigin(ServalaModelMixin, models.Model):
|
||||||
|
|
||||||
name = models.CharField(max_length=100, verbose_name=_("Name"))
|
name = models.CharField(max_length=100, verbose_name=_("Name"))
|
||||||
description = models.TextField(blank=True, verbose_name=_("Description"))
|
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:
|
class Meta:
|
||||||
verbose_name = _("Organization origin")
|
verbose_name = _("Organization origin")
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import base64
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from servala.core.models import (
|
from servala.core.models import (
|
||||||
|
BillingEntity,
|
||||||
Organization,
|
Organization,
|
||||||
OrganizationMembership,
|
OrganizationMembership,
|
||||||
OrganizationOrigin,
|
OrganizationOrigin,
|
||||||
|
|
@ -21,6 +22,11 @@ def origin():
|
||||||
return OrganizationOrigin.objects.create(name="TESTORIGIN")
|
return OrganizationOrigin.objects.create(name="TESTORIGIN")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def billing_entity():
|
||||||
|
return BillingEntity.objects.create(name="Test Entity")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def organization(origin):
|
def organization(origin):
|
||||||
return Organization.objects.create(name="Test Org", origin=origin)
|
return Organization.objects.create(name="Test Org", origin=origin)
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,36 @@ def test_successful_onboarding_new_organization(
|
||||||
assert "redis/offering/" in welcome_email.body
|
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
|
@pytest.mark.django_db
|
||||||
def test_duplicate_organization_returns_existing(
|
def test_duplicate_organization_returns_existing(
|
||||||
osb_client,
|
osb_client,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue