From f8c6e135e13f7548e01f4254d9f22d1a4c8e34c7 Mon Sep 17 00:00:00 2001
From: Daniel Egger
Date: Fri, 31 May 2024 14:05:42 +0200
Subject: [PATCH] Add fake datatrans endpoints for e2e tests
---
.../pages/onboarding/vv/CheckoutAddress.vue | 1 -
server/config/settings/base.py | 8 +-
server/config/settings/test_cypress.py | 3 +
server/config/urls.py | 15 ++
server/vbv_lernwelt/api/tests/test_me_api.py | 2 +-
server/vbv_lernwelt/core/model_utils.py | 5 +-
server/vbv_lernwelt/shop/README.md | 4 +-
.../shop/datatrans_fake_server.py | 161 ++++++++++++++++++
server/vbv_lernwelt/shop/invoice/abacus.py | 34 +++-
...013_checkoutinformation_abacus_order_id.py | 6 +-
server/vbv_lernwelt/shop/services.py | 6 +-
.../shop/tests/test_checkout_api.py | 79 +++------
.../shop/tests/test_datatrans_service.py | 6 +-
.../shop/tests/test_datatrans_webhook.py | 21 ++-
.../vbv_lernwelt/shop/tests/test_invoice.py | 24 +--
server/vbv_lernwelt/shop/views.py | 14 +-
16 files changed, 285 insertions(+), 104 deletions(-)
create mode 100644 server/vbv_lernwelt/shop/datatrans_fake_server.py
diff --git a/client/src/pages/onboarding/vv/CheckoutAddress.vue b/client/src/pages/onboarding/vv/CheckoutAddress.vue
index f1076318..ad6b2451 100644
--- a/client/src/pages/onboarding/vv/CheckoutAddress.vue
+++ b/client/src/pages/onboarding/vv/CheckoutAddress.vue
@@ -211,7 +211,6 @@ const executePayment = async () => {
{{ $t("a.Adresse") }}
- {{ address }}
{{
$t(
diff --git a/server/config/settings/base.py b/server/config/settings/base.py
index 6a342330..29c1f8b3 100644
--- a/server/config/settings/base.py
+++ b/server/config/settings/base.py
@@ -675,8 +675,12 @@ if APP_ENVIRONMENT.startswith("prod"):
DATATRANS_API_ENDPOINT = "https://api.datatrans.com"
DATATRANS_PAY_URL = "https://pay.datatrans.com"
else:
- DATATRANS_API_ENDPOINT = "https://api.sandbox.datatrans.com"
- DATATRANS_PAY_URL = "https://pay.sandbox.datatrans.com"
+ DATATRANS_API_ENDPOINT = env(
+ "DATATRANS_API_ENDPOINT", default="https://api.sandbox.datatrans.com"
+ )
+ DATATRANS_PAY_URL = env(
+ "DATATRANS_PAY_URL", default="https://pay.sandbox.datatrans.com"
+ )
# Only for debugging the webhook (locally)
DATATRANS_DEBUG_WEBHOOK_OVERWRITE = env(
diff --git a/server/config/settings/test_cypress.py b/server/config/settings/test_cypress.py
index 926fcea3..08ea70d2 100644
--- a/server/config/settings/test_cypress.py
+++ b/server/config/settings/test_cypress.py
@@ -14,6 +14,9 @@ from .base import * # noqa
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
DATABASES["default"]["NAME"] = "vbv_lernwelt_cypress"
+DATATRANS_API_ENDPOINT = 'http://localhost:8001/server/fakeapi/datatrans/api'
+DATATRANS_PAY_URL = 'http://localhost:8001/server/fakeapi/datatrans/pay'
+
# EMAIL
# ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend
diff --git a/server/config/urls.py b/server/config/urls.py
index 1bd57c20..d7f64dc1 100644
--- a/server/config/urls.py
+++ b/server/config/urls.py
@@ -68,6 +68,11 @@ from wagtail import urls as wagtail_urls
from wagtail.admin import urls as wagtailadmin_urls
from wagtail.documents import urls as media_library_urls
+from vbv_lernwelt.shop.datatrans_fake_server import (
+ fake_datatrans_api_view,
+ fake_datatrans_pay_view,
+)
+
class SignedIntConverter(IntConverter):
regex = r"-?\d+"
@@ -242,6 +247,16 @@ if settings.DEBUG:
# Static file serving when using Gunicorn + Uvicorn for local web socket development
urlpatterns += staticfiles_urlpatterns()
+if "fakeapi" in settings.DATATRANS_API_ENDPOINT:
+ urlpatterns += [
+ re_path(
+ r"^server/fakeapi/datatrans/api(?P.*)$", fake_datatrans_api_view
+ ),
+ re_path(
+ r"^server/fakeapi/datatrans/pay(?P.*)$", fake_datatrans_pay_view
+ ),
+ ]
+
# fmt: on
diff --git a/server/vbv_lernwelt/api/tests/test_me_api.py b/server/vbv_lernwelt/api/tests/test_me_api.py
index 2e6442f9..0cca97df 100644
--- a/server/vbv_lernwelt/api/tests/test_me_api.py
+++ b/server/vbv_lernwelt/api/tests/test_me_api.py
@@ -13,7 +13,7 @@ class MeUserViewTest(APITestCase):
)
self.client.login(username="testuser", password="testpassword")
add_organisations()
- add_countries()
+ add_countries(small_set=True)
def test_user_can_update_language(self) -> None:
# GIVEN
diff --git a/server/vbv_lernwelt/core/model_utils.py b/server/vbv_lernwelt/core/model_utils.py
index 634d9024..754fdebc 100644
--- a/server/vbv_lernwelt/core/model_utils.py
+++ b/server/vbv_lernwelt/core/model_utils.py
@@ -1011,7 +1011,7 @@ countries = {
}
-def add_countries(apps=None, schema_editor=None):
+def add_countries(apps=None, schema_editor=None, small_set=False):
if apps is None:
# pylint: disable=import-outside-toplevel
from vbv_lernwelt.core.models import Country
@@ -1025,6 +1025,9 @@ def add_countries(apps=None, schema_editor=None):
for country_id, country_name in countries.items():
country_code = country_name["country_code"]
+ if small_set and country_code not in ["CH", "LI", "DE", "AT", "FR", "IT"]:
+ continue
+
if has_country_code:
Country.objects.get_or_create(
country_code=country_code,
diff --git a/server/vbv_lernwelt/shop/README.md b/server/vbv_lernwelt/shop/README.md
index 95fed595..cabdbadc 100644
--- a/server/vbv_lernwelt/shop/README.md
+++ b/server/vbv_lernwelt/shop/README.md
@@ -76,4 +76,6 @@ After everything runs fine, we should be able to remove the following deprecated
### Datatrans Test Credit Card
-5100 0010 0000 0014 06/25 123
+5100 0010 0000 0014
+06/25
+123
diff --git a/server/vbv_lernwelt/shop/datatrans_fake_server.py b/server/vbv_lernwelt/shop/datatrans_fake_server.py
new file mode 100644
index 00000000..699363a3
--- /dev/null
+++ b/server/vbv_lernwelt/shop/datatrans_fake_server.py
@@ -0,0 +1,161 @@
+import hashlib
+import hmac
+import json
+import threading
+
+from django.conf import settings
+from django.http import HttpResponse, JsonResponse
+from django.shortcuts import redirect
+from django.views.decorators.csrf import csrf_exempt
+
+from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
+from vbv_lernwelt.core.models import User
+
+
+@csrf_exempt
+@django_view_authentication_exempt
+def fake_datatrans_api_view(request, api_url=""):
+ # if api_url == "/redirect":
+ # fake_tamedia_token = request.GET.get("token")
+ # pai = fake_tamedia_token.split(":")[1]
+ # sub = SubhubCustomerSubscription.objects.filter(id=pai).first()
+ #
+ # header = f"fake tamedia activation for {pai}"
+ #
+ # if not sub:
+ # return HttpResponse(
+ # content=f"""
+ # {header}
+ #
no subscription found
+ # """,
+ # status=404,
+ # )
+ #
+ # if request.method == "GET":
+ # if (
+ # sub
+ # and sub.partner_status
+ # == SubhubCustomerSubscription.PARTNER_STATUS_ENROLLED
+ # ):
+ # return HttpResponse(
+ # content=f"""
+ # {header}
+ #
+ #
+ #
+ #
+ # """,
+ # status=200,
+ # )
+ # else:
+ # return HttpResponse(
+ # content=f"""
+ # {header}
+ # already activated
+ # """,
+ # status=200,
+ # )
+ # if request.method == "POST":
+ # if sub:
+ # response = requests.post(
+ # f"{settings.APPLICATION_ABSOLUTE_URL}/subhub/ottwebhook",
+ # json={
+ # "PartnerIntegration": {
+ # "effectiveDate": datetime.now().isoformat(),
+ # "eventType": "activation",
+ # "offerId": sub.subscription_choice.partner_product_id,
+ # "optionalAttributes": None,
+ # "pai": pai,
+ # "partnerType": "Tamedia",
+ # "transactionId": str(uuid.uuid4()),
+ # },
+ # "eventId": str(uuid.uuid4()),
+ # "eventType": "OTT Partner Events",
+ # "publisherId": "Partner Events",
+ # "status": "new",
+ # "timestamp": datetime.now().isoformat(),
+ # },
+ # auth=HTTPBasicAuth(
+ # "swisscom_ott_webhook",
+ # "swisscom-ott-webhook-rLaYG0btVJMPtfnzfLilZtm50",
+ # ),
+ # )
+ # print(response)
+ # return redirect(f"{create_register_url(fake_tamedia_token)}")
+ #
+ # if api_url.startswith("/enroll") and request.method == "POST":
+ # return HttpResponse(status=204)
+ #
+
+ if api_url == "/v1/transactions" and request.method == "POST":
+ data = json.loads(request.body.decode("utf-8"))
+ user = User.objects.get(id=data["user_id"])
+ user.additional_json_data["datatrans_transaction_payload"] = data
+ user.save()
+ return JsonResponse({"transactionId": data["refno"]}, status=201)
+
+ return HttpResponse(
+ content="unknown api url", content_type="application/json", status=400
+ )
+
+
+@csrf_exempt
+@django_view_authentication_exempt
+def fake_datatrans_pay_view(request, api_url=""):
+ def call_transaction_complete_webhook(
+ webhook_url, transaction_id, datatrans_status="settled"
+ ):
+ import requests
+ import time
+
+ time.sleep(1)
+
+ payload = {
+ "transactionId": transaction_id,
+ "status": datatrans_status,
+ }
+ key_hex_bytes = bytes.fromhex(settings.DATATRANS_HMAC_KEY)
+
+ # Create sign with timestamp and payload
+ sign = hmac.new(key_hex_bytes, bytes(str(1) + json.dumps(payload), "utf-8"), hashlib.sha256)
+
+ response = requests.post(
+ url=webhook_url,
+ json=payload,
+ headers={
+ "Datatrans-Signature": f"t=1,s0={sign.hexdigest()}"
+ },
+ )
+ print(response)
+
+ if api_url.startswith("/v1/start/") and request.method == "GET":
+ transaction_id = api_url.split("/")[-1]
+ transaction_user = User.objects.filter(
+ additional_json_data__datatrans_transaction_payload__refno=transaction_id
+ ).first()
+
+ redirect_url = transaction_user.additional_json_data[
+ "datatrans_transaction_payload"
+ ]["redirect"]["successUrl"]
+
+ # start new thread which will call webhook after 2 seconds
+ webhook_url = transaction_user.additional_json_data[
+ "datatrans_transaction_payload"
+ ]["webhook"]["url"]
+ thread = threading.Thread(
+ target=call_transaction_complete_webhook,
+ args=(
+ webhook_url,
+ transaction_id,
+ ),
+ )
+ thread.start()
+
+ # redirect to url
+ return redirect(redirect_url + f"?datatransTrxId={transaction_id}")
+
+ return HttpResponse(
+ content="unknown api url", content_type="application/json", status=400
+ )
diff --git a/server/vbv_lernwelt/shop/invoice/abacus.py b/server/vbv_lernwelt/shop/invoice/abacus.py
index 2725e8ee..747d343b 100644
--- a/server/vbv_lernwelt/shop/invoice/abacus.py
+++ b/server/vbv_lernwelt/shop/invoice/abacus.py
@@ -72,17 +72,34 @@ def create_customer_xml(checkout_information: CheckoutInformation):
abacus_debitor_number=customer.abacus_debitor_number,
last_name=checkout_information.last_name,
first_name=checkout_information.first_name,
- company_name=checkout_information.company_name,
- street=(checkout_information.company_street or checkout_information.street),
+ company_name=checkout_information.organisation_detail_name
+ if checkout_information.invoice_address == "org"
+ else "",
+ street=(
+ checkout_information.organisation_street
+ if checkout_information.invoice_address == "org"
+ else checkout_information.street
+ ),
house_number=(
- checkout_information.company_street_number
- or checkout_information.street_number
+ checkout_information.organisation_street_number
+ if checkout_information.invoice_address == "org"
+ else checkout_information.street_number
),
zip_code=(
- checkout_information.company_postal_code or checkout_information.postal_code
+ checkout_information.organisation_postal_code
+ if checkout_information.invoice_address == "org"
+ else checkout_information.postal_code
+ ),
+ city=(
+ checkout_information.organisation_city
+ if checkout_information.invoice_address == "org"
+ else checkout_information.city
+ ),
+ country=(
+ checkout_information.organisation_country_id
+ if checkout_information.invoice_address == "org"
+ else checkout_information.country_id
),
- city=(checkout_information.company_city or checkout_information.city),
- country=(checkout_information.company_country or checkout_information.country),
language=customer.language,
email=customer.email,
)
@@ -187,7 +204,8 @@ def render_customer_xml(
SubElement(address_data, "AddressNumber").text = str(abacus_debitor_number)
SubElement(address_data, "Name").text = last_name
SubElement(address_data, "FirstName").text = first_name
- SubElement(address_data, "Text").text = company_name
+ if company_name:
+ SubElement(address_data, "Text").text = company_name
SubElement(address_data, "Street").text = street
SubElement(address_data, "HouseNumber").text = house_number
SubElement(address_data, "ZIP").text = zip_code
diff --git a/server/vbv_lernwelt/shop/migrations/0013_checkoutinformation_abacus_order_id.py b/server/vbv_lernwelt/shop/migrations/0013_checkoutinformation_abacus_order_id.py
index 951991e4..3073b3db 100644
--- a/server/vbv_lernwelt/shop/migrations/0013_checkoutinformation_abacus_order_id.py
+++ b/server/vbv_lernwelt/shop/migrations/0013_checkoutinformation_abacus_order_id.py
@@ -13,7 +13,8 @@ def migrate_checkout_information_country(apps, schema_editor):
if info.old_company_country:
country = Country.objects.get(vbv_country_id=info.old_company_country)
info.organisation_country = country
- info.save(update_fields=["country", "organisation_country"])
+ info.invoice_address = "org"
+ info.save(update_fields=["country", "organisation_country", "invoice_address"])
class Migration(migrations.Migration):
@@ -103,4 +104,7 @@ class Migration(migrations.Migration):
model_name="checkoutinformation",
name="old_company_country",
),
+ migrations.DeleteModel(
+ name='BillingAddress',
+ ),
]
diff --git a/server/vbv_lernwelt/shop/services.py b/server/vbv_lernwelt/shop/services.py
index 9a2d1faa..bad18346 100644
--- a/server/vbv_lernwelt/shop/services.py
+++ b/server/vbv_lernwelt/shop/services.py
@@ -45,7 +45,7 @@ def is_signature_valid(
return s0_actual == s0_expected
-def init_transaction(
+def init_datatrans_transaction(
user: User,
amount_chf_centimes: int,
redirect_url_success: str,
@@ -76,6 +76,10 @@ def init_transaction(
},
}
+ # add testing configuration data
+ if 'fakeapi' in settings.DATATRANS_API_ENDPOINT:
+ payload['user_id'] = str(user.id)
+
logger.info("Initiating transaction", payload=payload)
response = requests.post(
diff --git a/server/vbv_lernwelt/shop/tests/test_checkout_api.py b/server/vbv_lernwelt/shop/tests/test_checkout_api.py
index 7b0de51b..02228de8 100644
--- a/server/vbv_lernwelt/shop/tests/test_checkout_api.py
+++ b/server/vbv_lernwelt/shop/tests/test_checkout_api.py
@@ -21,13 +21,14 @@ TEST_ADDRESS_DATA = {
"street_number": "1",
"postal_code": "1234",
"city": "Test City",
- "country": "209",
- "company_name": "Test Company",
- "company_street": "Test Company Street",
- "company_street_number": "1",
- "company_postal_code": "1234",
- "company_city": "Test Company City",
- "company_country": "209",
+ "country_code": "CH",
+ "invoice_address": "org",
+ "organisation_detail_name": "Test Company",
+ "organisation_street": "Test Company Street",
+ "organisation_street_number": "1",
+ "organisation_postal_code": "1234",
+ "organisation_city": "Test Company City",
+ "organisation_country_code": "CH",
}
REDIRECT_URL = "http://testserver/redirect-url"
@@ -50,40 +51,9 @@ class CheckoutAPITestCase(APITestCase):
)
self.client.login(username=USER_USERNAME, password=USER_PASSWORD)
- add_countries()
+ add_countries(small_set=True)
- @patch("vbv_lernwelt.shop.views.init_transaction")
- def test_checkout_no_company_address_updates_user(self, mock_init_transaction):
- # GIVEN
- mock_init_transaction.return_value = "1234567890"
-
- # WHEN
- response = self.client.post(
- path=reverse("checkout-vv"),
- format="json",
- data={
- "redirect_url": REDIRECT_URL,
- "product": VV_DE_PRODUCT_SKU,
- "address": {
- "first_name": "Test",
- "last_name": "User",
- "street": "Test Street",
- "street_number": "1",
- "postal_code": "1234",
- "city": "Test City",
- "country": "209",
- # NO company data
- },
- },
- )
-
- # THEN
- self.assertEqual(response.status_code, status.HTTP_200_OK)
-
- user = User.objects.get(username=USER_USERNAME)
- self.assertEqual(user.invoice_address, User.INVOICE_ADDRESS_PRIVATE)
-
- @patch("vbv_lernwelt.shop.views.init_transaction")
+ @patch("vbv_lernwelt.shop.views.init_datatrans_transaction")
def test_checkout_happy_case(self, mock_init_transaction):
# GIVEN
mock_init_transaction.return_value = "1234567890"
@@ -106,13 +76,12 @@ class CheckoutAPITestCase(APITestCase):
response.json()["next_step_url"],
)
- self.assertTrue(
- CheckoutInformation.objects.filter(
- user=self.user,
- product_sku=VV_DE_PRODUCT_SKU,
- state=CheckoutState.ONGOING,
- ).exists()
- )
+ ci = CheckoutInformation.objects.first()
+ self.assertEqual(ci.first_name, "Test")
+ self.assertEqual(ci.last_name, "User")
+ self.assertEqual(ci.country_id, "CH")
+ self.assertEqual(ci.state, "ongoing")
+ self.assertEqual(ci.transaction_id, "1234567890")
mock_init_transaction.assert_called_once_with(
user=self.user,
@@ -123,13 +92,7 @@ class CheckoutAPITestCase(APITestCase):
webhook_url=f"{REDIRECT_URL}/api/shop/transaction/webhook/",
)
- user = User.objects.get(username=USER_USERNAME)
-
- self.assertEqual(user.street, TEST_ADDRESS_DATA["street"])
- self.assertEqual(str(user.country.country_id), TEST_ADDRESS_DATA["country"])
- self.assertEqual(user.invoice_address, User.INVOICE_ADDRESS_ORGANISATION)
-
- @patch("vbv_lernwelt.shop.views.init_transaction")
+ @patch("vbv_lernwelt.shop.views.init_datatrans_transaction")
def test_incomplete_setup(self, mock_init_transaction):
# GIVEN
Product.objects.all().delete()
@@ -156,7 +119,7 @@ class CheckoutAPITestCase(APITestCase):
self.assertEqual(expected, response.json()["next_step_url"])
- @patch("vbv_lernwelt.shop.views.init_transaction")
+ @patch("vbv_lernwelt.shop.views.init_datatrans_transaction")
def test_checkout_init_transaction_exception(self, mock_init_transaction):
# GIVEN
mock_init_transaction.side_effect = InitTransactionException(
@@ -213,7 +176,7 @@ class CheckoutAPITestCase(APITestCase):
response.json()["next_step_url"],
)
- @patch("vbv_lernwelt.shop.views.init_transaction")
+ @patch("vbv_lernwelt.shop.views.init_datatrans_transaction")
def test_checkout_double_checkout(self, mock_init_transaction):
"""Advise by Datatrans: Just create a new transaction."""
# GIVEN
@@ -277,7 +240,7 @@ class CheckoutAPITestCase(APITestCase):
).exists()
)
- @patch("vbv_lernwelt.shop.views.init_transaction")
+ @patch("vbv_lernwelt.shop.views.init_datatrans_transaction")
def test_checkout_failed_creates_new(self, mock_init_transaction):
# GIVEN
state = CheckoutState.FAILED
@@ -310,7 +273,7 @@ class CheckoutAPITestCase(APITestCase):
response.json()["next_step_url"],
)
- @patch("vbv_lernwelt.shop.views.init_transaction")
+ @patch("vbv_lernwelt.shop.views.init_datatrans_transaction")
def test_checkout_cancelled_creates_new(self, mock_init_transaction):
# GIVEN
state = CheckoutState.CANCELED
diff --git a/server/vbv_lernwelt/shop/tests/test_datatrans_service.py b/server/vbv_lernwelt/shop/tests/test_datatrans_service.py
index f4a54039..9d3aca8a 100644
--- a/server/vbv_lernwelt/shop/tests/test_datatrans_service.py
+++ b/server/vbv_lernwelt/shop/tests/test_datatrans_service.py
@@ -6,7 +6,7 @@ from django.test import override_settings, TestCase
from vbv_lernwelt.core.models import User
from vbv_lernwelt.shop.services import (
get_payment_url,
- init_transaction,
+ init_datatrans_transaction,
InitTransactionException,
)
@@ -36,7 +36,7 @@ class DatatransServiceTest(TestCase):
self.user.language = "it"
# WHEN
- transaction_id = init_transaction(
+ transaction_id = init_datatrans_transaction(
user=self.user,
amount_chf_centimes=324_30,
redirect_url_success=f"{REDIRECT_URL}/success",
@@ -76,7 +76,7 @@ class DatatransServiceTest(TestCase):
# WHEN / THEN
with self.assertRaises(InitTransactionException):
- init_transaction(
+ init_datatrans_transaction(
user=self.user,
amount_chf_centimes=324_30,
redirect_url_success=f"/success",
diff --git a/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py b/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py
index c18f7e6c..d8b79c99 100644
--- a/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py
+++ b/server/vbv_lernwelt/shop/tests/test_datatrans_webhook.py
@@ -5,6 +5,7 @@ from rest_framework import status
from rest_framework.test import APITestCase
from vbv_lernwelt.core.admin import User
+from vbv_lernwelt.core.model_utils import add_countries
from vbv_lernwelt.course.consts import COURSE_VERSICHERUNGSVERMITTLERIN_ID
from vbv_lernwelt.course.creators.test_utils import create_course, create_course_session
from vbv_lernwelt.course.models import CourseSessionUser
@@ -29,6 +30,8 @@ def create_checkout_information(
class DatatransWebhookTestCase(APITestCase):
def setUp(self) -> None:
+ add_countries(small_set=True)
+
course, _ = create_course(
title="VV_in_DE",
# needed for VV_DE_PRODUCT_SKU
@@ -102,13 +105,13 @@ class DatatransWebhookTestCase(APITestCase):
checkout_info.street_number = "1"
checkout_info.postal_code = "1234"
checkout_info.city = "Musterstadt"
- checkout_info.country = "Schweiz"
- checkout_info.company_name = "Musterfirma"
- checkout_info.company_street = "Firmastrasse"
- checkout_info.company_street_number = "2"
- checkout_info.company_postal_code = "5678"
- checkout_info.company_city = "Firmastadt"
- checkout_info.company_country = "Schweiz"
+ checkout_info.country_id = "CH"
+ checkout_info.organisation_detail_name = "Musterfirma"
+ checkout_info.organisation_street = "Firmastrasse"
+ checkout_info.organisation_street_number = "2"
+ checkout_info.organisation_postal_code = "5678"
+ checkout_info.organisation_city = "Firmastadt"
+ checkout_info.organisation_country_id = "CH"
checkout_info.save()
mock_is_signature_valid.return_value = True
@@ -181,10 +184,10 @@ class DatatransWebhookTestCase(APITestCase):
"target_url": "https://my.vbv-afa.ch/",
"name": "Max Mustermann",
"private_street": "Musterstrasse 1",
- "private_city": "1234 Musterstadt Schweiz",
+ "private_city": "CH-1234 Musterstadt",
"company_name": "Musterfirma",
"company_street": "Firmastrasse 2",
- "company_city": "5678 Firmastadt Schweiz",
+ "company_city": "CH-5678 Firmastadt",
},
template_language=self.user.language,
fail_silently=ANY,
diff --git a/server/vbv_lernwelt/shop/tests/test_invoice.py b/server/vbv_lernwelt/shop/tests/test_invoice.py
index ea16936b..10c384e1 100644
--- a/server/vbv_lernwelt/shop/tests/test_invoice.py
+++ b/server/vbv_lernwelt/shop/tests/test_invoice.py
@@ -5,6 +5,7 @@ from django.test import TestCase
from vbv_lernwelt.core.admin import User
from vbv_lernwelt.core.create_default_users import create_default_users
+from vbv_lernwelt.core.model_utils import add_countries
from vbv_lernwelt.shop.invoice.abacus import (
AbacusInvoiceCreator,
create_customer_xml,
@@ -23,6 +24,7 @@ USER_PASSWORD = "testpassword"
class AbacusInvoiceTestCase(TestCase):
def setUp(self):
+ add_countries(small_set=True)
create_default_users()
def test_create_invoice_xml(self):
@@ -136,13 +138,14 @@ class AbacusInvoiceTestCase(TestCase):
street_number="32",
postal_code="1719",
city="Zumholz",
- country="209",
- company_name="VBV",
- company_street="Laupenstrasse",
- company_street_number="10",
- company_postal_code="3000",
- company_city="Bern",
- company_country="209",
+ country_id="CH",
+ invoice_address="org",
+ organisation_detail_name="VBV",
+ organisation_street="Laupenstrasse",
+ organisation_street_number="10",
+ organisation_postal_code="3000",
+ organisation_city="Bern",
+ organisation_country_id="CH",
)
feuz_checkout_info.created_at = datetime(2024, 2, 15, 8, 33, 12, 0)
@@ -158,10 +161,11 @@ class AbacusInvoiceTestCase(TestCase):
"andreas.feuz@eiger-versicherungen.ch"
in customer_xml_content
)
+ assert "60000012" in customer_xml_content
+ assert "Feuz" in customer_xml_content
assert "VBV" in customer_xml_content
-
- # FIXME refactor country
- assert "209" in customer_xml_content
+ assert "Laupenstrasse" in customer_xml_content
+ assert "CH" in customer_xml_content
def test_render_customer_xml(self):
customer_xml = render_customer_xml(
diff --git a/server/vbv_lernwelt/shop/views.py b/server/vbv_lernwelt/shop/views.py
index ce7db598..e170cc5c 100644
--- a/server/vbv_lernwelt/shop/views.py
+++ b/server/vbv_lernwelt/shop/views.py
@@ -1,10 +1,8 @@
import structlog
from django.conf import settings
from django.http import JsonResponse
-from rest_framework import status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
-from rest_framework.response import Response
from sentry_sdk import capture_exception
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
@@ -18,7 +16,7 @@ from vbv_lernwelt.shop.models import CheckoutInformation, CheckoutState, Product
from vbv_lernwelt.shop.services import (
datatrans_state_to_checkout_state,
get_payment_url,
- init_transaction,
+ init_datatrans_transaction,
InitTransactionException,
is_signature_valid,
)
@@ -109,7 +107,7 @@ def checkout_vv(request):
return next_step_response(url="/")
try:
- transaction_id = init_transaction(
+ transaction_id = init_datatrans_transaction(
user=request.user,
amount_chf_centimes=product.price,
redirect_url_success=checkout_success_url(
@@ -176,10 +174,10 @@ def send_vv_welcome_email(checkout_info: CheckoutInformation):
"target_url": "https://my.vbv-afa.ch/",
"name": f"{checkout_info.first_name} {checkout_info.last_name}",
"private_street": f"{checkout_info.street} {checkout_info.street_number}",
- "private_city": f"{checkout_info.postal_code} {checkout_info.city} {checkout_info.country}",
- "company_name": checkout_info.company_name,
- "company_street": f"{checkout_info.company_street} {checkout_info.company_street_number}",
- "company_city": f"{checkout_info.company_postal_code} {checkout_info.company_city} {checkout_info.company_country}",
+ "private_city": f"{checkout_info.country_id}-{checkout_info.postal_code} {checkout_info.city}",
+ "company_name": checkout_info.organisation_detail_name,
+ "company_street": f"{checkout_info.organisation_street} {checkout_info.organisation_street_number}",
+ "company_city": f"{checkout_info.organisation_country_id}-{checkout_info.organisation_postal_code} {checkout_info.organisation_city}",
},
template_language=checkout_info.user.language,
fail_silently=True,