Add fake datatrans endpoints for e2e tests

This commit is contained in:
Daniel Egger 2024-05-31 14:05:42 +02:00
parent ec21238ece
commit f8c6e135e1
16 changed files with 285 additions and 104 deletions

View File

@ -211,7 +211,6 @@ const executePayment = async () => {
</p> </p>
<h3 class="mb-4 mt-10">{{ $t("a.Adresse") }}</h3> <h3 class="mb-4 mt-10">{{ $t("a.Adresse") }}</h3>
<pre>{{ address }}</pre>
<p class="mb-2"> <p class="mb-2">
{{ {{
$t( $t(

View File

@ -675,8 +675,12 @@ if APP_ENVIRONMENT.startswith("prod"):
DATATRANS_API_ENDPOINT = "https://api.datatrans.com" DATATRANS_API_ENDPOINT = "https://api.datatrans.com"
DATATRANS_PAY_URL = "https://pay.datatrans.com" DATATRANS_PAY_URL = "https://pay.datatrans.com"
else: else:
DATATRANS_API_ENDPOINT = "https://api.sandbox.datatrans.com" DATATRANS_API_ENDPOINT = env(
DATATRANS_PAY_URL = "https://pay.sandbox.datatrans.com" "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) # Only for debugging the webhook (locally)
DATATRANS_DEBUG_WEBHOOK_OVERWRITE = env( DATATRANS_DEBUG_WEBHOOK_OVERWRITE = env(

View File

@ -14,6 +14,9 @@ from .base import * # noqa
# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key # https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
DATABASES["default"]["NAME"] = "vbv_lernwelt_cypress" 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 # EMAIL
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend # https://docs.djangoproject.com/en/dev/ref/settings/#email-backend

View File

@ -68,6 +68,11 @@ from wagtail import urls as wagtail_urls
from wagtail.admin import urls as wagtailadmin_urls from wagtail.admin import urls as wagtailadmin_urls
from wagtail.documents import urls as media_library_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): class SignedIntConverter(IntConverter):
regex = r"-?\d+" regex = r"-?\d+"
@ -242,6 +247,16 @@ if settings.DEBUG:
# Static file serving when using Gunicorn + Uvicorn for local web socket development # Static file serving when using Gunicorn + Uvicorn for local web socket development
urlpatterns += staticfiles_urlpatterns() urlpatterns += staticfiles_urlpatterns()
if "fakeapi" in settings.DATATRANS_API_ENDPOINT:
urlpatterns += [
re_path(
r"^server/fakeapi/datatrans/api(?P<api_url>.*)$", fake_datatrans_api_view
),
re_path(
r"^server/fakeapi/datatrans/pay(?P<api_url>.*)$", fake_datatrans_pay_view
),
]
# fmt: on # fmt: on

View File

@ -13,7 +13,7 @@ class MeUserViewTest(APITestCase):
) )
self.client.login(username="testuser", password="testpassword") self.client.login(username="testuser", password="testpassword")
add_organisations() add_organisations()
add_countries() add_countries(small_set=True)
def test_user_can_update_language(self) -> None: def test_user_can_update_language(self) -> None:
# GIVEN # GIVEN

View File

@ -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: if apps is None:
# pylint: disable=import-outside-toplevel # pylint: disable=import-outside-toplevel
from vbv_lernwelt.core.models import Country 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(): for country_id, country_name in countries.items():
country_code = country_name["country_code"] 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: if has_country_code:
Country.objects.get_or_create( Country.objects.get_or_create(
country_code=country_code, country_code=country_code,

View File

@ -76,4 +76,6 @@ After everything runs fine, we should be able to remove the following deprecated
### Datatrans Test Credit Card ### Datatrans Test Credit Card
5100 0010 0000 0014 06/25 123 5100 0010 0000 0014
06/25
123

View File

@ -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"<h1>fake tamedia activation for {pai}"
#
# if not sub:
# return HttpResponse(
# content=f"""
# {header}
# <p>no subscription found</p>
# """,
# status=404,
# )
#
# if request.method == "GET":
# if (
# sub
# and sub.partner_status
# == SubhubCustomerSubscription.PARTNER_STATUS_ENROLLED
# ):
# return HttpResponse(
# content=f"""
# {header}
# <div>
# <input type="text" name="partnerSubscriptionId" value="{pai}">
# <form action="{create_register_url(fake_tamedia_token)}" method="post">
# <button type="submit" data-cy="register-button">Register</button>
# </form>
# </div>
# """,
# status=200,
# )
# else:
# return HttpResponse(
# content=f"""
# {header}
# <p>already activated</p>
# """,
# 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
)

View File

@ -72,17 +72,34 @@ def create_customer_xml(checkout_information: CheckoutInformation):
abacus_debitor_number=customer.abacus_debitor_number, abacus_debitor_number=customer.abacus_debitor_number,
last_name=checkout_information.last_name, last_name=checkout_information.last_name,
first_name=checkout_information.first_name, first_name=checkout_information.first_name,
company_name=checkout_information.company_name, company_name=checkout_information.organisation_detail_name
street=(checkout_information.company_street or checkout_information.street), if checkout_information.invoice_address == "org"
else "",
street=(
checkout_information.organisation_street
if checkout_information.invoice_address == "org"
else checkout_information.street
),
house_number=( house_number=(
checkout_information.company_street_number checkout_information.organisation_street_number
or checkout_information.street_number if checkout_information.invoice_address == "org"
else checkout_information.street_number
), ),
zip_code=( 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, language=customer.language,
email=customer.email, email=customer.email,
) )
@ -187,7 +204,8 @@ def render_customer_xml(
SubElement(address_data, "AddressNumber").text = str(abacus_debitor_number) SubElement(address_data, "AddressNumber").text = str(abacus_debitor_number)
SubElement(address_data, "Name").text = last_name SubElement(address_data, "Name").text = last_name
SubElement(address_data, "FirstName").text = first_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, "Street").text = street
SubElement(address_data, "HouseNumber").text = house_number SubElement(address_data, "HouseNumber").text = house_number
SubElement(address_data, "ZIP").text = zip_code SubElement(address_data, "ZIP").text = zip_code

View File

@ -13,7 +13,8 @@ def migrate_checkout_information_country(apps, schema_editor):
if info.old_company_country: if info.old_company_country:
country = Country.objects.get(vbv_country_id=info.old_company_country) country = Country.objects.get(vbv_country_id=info.old_company_country)
info.organisation_country = 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): class Migration(migrations.Migration):
@ -103,4 +104,7 @@ class Migration(migrations.Migration):
model_name="checkoutinformation", model_name="checkoutinformation",
name="old_company_country", name="old_company_country",
), ),
migrations.DeleteModel(
name='BillingAddress',
),
] ]

View File

@ -45,7 +45,7 @@ def is_signature_valid(
return s0_actual == s0_expected return s0_actual == s0_expected
def init_transaction( def init_datatrans_transaction(
user: User, user: User,
amount_chf_centimes: int, amount_chf_centimes: int,
redirect_url_success: str, 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) logger.info("Initiating transaction", payload=payload)
response = requests.post( response = requests.post(

View File

@ -21,13 +21,14 @@ TEST_ADDRESS_DATA = {
"street_number": "1", "street_number": "1",
"postal_code": "1234", "postal_code": "1234",
"city": "Test City", "city": "Test City",
"country": "209", "country_code": "CH",
"company_name": "Test Company", "invoice_address": "org",
"company_street": "Test Company Street", "organisation_detail_name": "Test Company",
"company_street_number": "1", "organisation_street": "Test Company Street",
"company_postal_code": "1234", "organisation_street_number": "1",
"company_city": "Test Company City", "organisation_postal_code": "1234",
"company_country": "209", "organisation_city": "Test Company City",
"organisation_country_code": "CH",
} }
REDIRECT_URL = "http://testserver/redirect-url" REDIRECT_URL = "http://testserver/redirect-url"
@ -50,40 +51,9 @@ class CheckoutAPITestCase(APITestCase):
) )
self.client.login(username=USER_USERNAME, password=USER_PASSWORD) self.client.login(username=USER_USERNAME, password=USER_PASSWORD)
add_countries() add_countries(small_set=True)
@patch("vbv_lernwelt.shop.views.init_transaction") @patch("vbv_lernwelt.shop.views.init_datatrans_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")
def test_checkout_happy_case(self, mock_init_transaction): def test_checkout_happy_case(self, mock_init_transaction):
# GIVEN # GIVEN
mock_init_transaction.return_value = "1234567890" mock_init_transaction.return_value = "1234567890"
@ -106,13 +76,12 @@ class CheckoutAPITestCase(APITestCase):
response.json()["next_step_url"], response.json()["next_step_url"],
) )
self.assertTrue( ci = CheckoutInformation.objects.first()
CheckoutInformation.objects.filter( self.assertEqual(ci.first_name, "Test")
user=self.user, self.assertEqual(ci.last_name, "User")
product_sku=VV_DE_PRODUCT_SKU, self.assertEqual(ci.country_id, "CH")
state=CheckoutState.ONGOING, self.assertEqual(ci.state, "ongoing")
).exists() self.assertEqual(ci.transaction_id, "1234567890")
)
mock_init_transaction.assert_called_once_with( mock_init_transaction.assert_called_once_with(
user=self.user, user=self.user,
@ -123,13 +92,7 @@ class CheckoutAPITestCase(APITestCase):
webhook_url=f"{REDIRECT_URL}/api/shop/transaction/webhook/", webhook_url=f"{REDIRECT_URL}/api/shop/transaction/webhook/",
) )
user = User.objects.get(username=USER_USERNAME) @patch("vbv_lernwelt.shop.views.init_datatrans_transaction")
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")
def test_incomplete_setup(self, mock_init_transaction): def test_incomplete_setup(self, mock_init_transaction):
# GIVEN # GIVEN
Product.objects.all().delete() Product.objects.all().delete()
@ -156,7 +119,7 @@ class CheckoutAPITestCase(APITestCase):
self.assertEqual(expected, response.json()["next_step_url"]) 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): def test_checkout_init_transaction_exception(self, mock_init_transaction):
# GIVEN # GIVEN
mock_init_transaction.side_effect = InitTransactionException( mock_init_transaction.side_effect = InitTransactionException(
@ -213,7 +176,7 @@ class CheckoutAPITestCase(APITestCase):
response.json()["next_step_url"], 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): def test_checkout_double_checkout(self, mock_init_transaction):
"""Advise by Datatrans: Just create a new transaction.""" """Advise by Datatrans: Just create a new transaction."""
# GIVEN # GIVEN
@ -277,7 +240,7 @@ class CheckoutAPITestCase(APITestCase):
).exists() ).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): def test_checkout_failed_creates_new(self, mock_init_transaction):
# GIVEN # GIVEN
state = CheckoutState.FAILED state = CheckoutState.FAILED
@ -310,7 +273,7 @@ class CheckoutAPITestCase(APITestCase):
response.json()["next_step_url"], 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): def test_checkout_cancelled_creates_new(self, mock_init_transaction):
# GIVEN # GIVEN
state = CheckoutState.CANCELED state = CheckoutState.CANCELED

View File

@ -6,7 +6,7 @@ from django.test import override_settings, TestCase
from vbv_lernwelt.core.models import User from vbv_lernwelt.core.models import User
from vbv_lernwelt.shop.services import ( from vbv_lernwelt.shop.services import (
get_payment_url, get_payment_url,
init_transaction, init_datatrans_transaction,
InitTransactionException, InitTransactionException,
) )
@ -36,7 +36,7 @@ class DatatransServiceTest(TestCase):
self.user.language = "it" self.user.language = "it"
# WHEN # WHEN
transaction_id = init_transaction( transaction_id = init_datatrans_transaction(
user=self.user, user=self.user,
amount_chf_centimes=324_30, amount_chf_centimes=324_30,
redirect_url_success=f"{REDIRECT_URL}/success", redirect_url_success=f"{REDIRECT_URL}/success",
@ -76,7 +76,7 @@ class DatatransServiceTest(TestCase):
# WHEN / THEN # WHEN / THEN
with self.assertRaises(InitTransactionException): with self.assertRaises(InitTransactionException):
init_transaction( init_datatrans_transaction(
user=self.user, user=self.user,
amount_chf_centimes=324_30, amount_chf_centimes=324_30,
redirect_url_success=f"/success", redirect_url_success=f"/success",

View File

@ -5,6 +5,7 @@ from rest_framework import status
from rest_framework.test import APITestCase from rest_framework.test import APITestCase
from vbv_lernwelt.core.admin import User 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.consts import COURSE_VERSICHERUNGSVERMITTLERIN_ID
from vbv_lernwelt.course.creators.test_utils import create_course, create_course_session from vbv_lernwelt.course.creators.test_utils import create_course, create_course_session
from vbv_lernwelt.course.models import CourseSessionUser from vbv_lernwelt.course.models import CourseSessionUser
@ -29,6 +30,8 @@ def create_checkout_information(
class DatatransWebhookTestCase(APITestCase): class DatatransWebhookTestCase(APITestCase):
def setUp(self) -> None: def setUp(self) -> None:
add_countries(small_set=True)
course, _ = create_course( course, _ = create_course(
title="VV_in_DE", title="VV_in_DE",
# needed for VV_DE_PRODUCT_SKU # needed for VV_DE_PRODUCT_SKU
@ -102,13 +105,13 @@ class DatatransWebhookTestCase(APITestCase):
checkout_info.street_number = "1" checkout_info.street_number = "1"
checkout_info.postal_code = "1234" checkout_info.postal_code = "1234"
checkout_info.city = "Musterstadt" checkout_info.city = "Musterstadt"
checkout_info.country = "Schweiz" checkout_info.country_id = "CH"
checkout_info.company_name = "Musterfirma" checkout_info.organisation_detail_name = "Musterfirma"
checkout_info.company_street = "Firmastrasse" checkout_info.organisation_street = "Firmastrasse"
checkout_info.company_street_number = "2" checkout_info.organisation_street_number = "2"
checkout_info.company_postal_code = "5678" checkout_info.organisation_postal_code = "5678"
checkout_info.company_city = "Firmastadt" checkout_info.organisation_city = "Firmastadt"
checkout_info.company_country = "Schweiz" checkout_info.organisation_country_id = "CH"
checkout_info.save() checkout_info.save()
mock_is_signature_valid.return_value = True mock_is_signature_valid.return_value = True
@ -181,10 +184,10 @@ class DatatransWebhookTestCase(APITestCase):
"target_url": "https://my.vbv-afa.ch/", "target_url": "https://my.vbv-afa.ch/",
"name": "Max Mustermann", "name": "Max Mustermann",
"private_street": "Musterstrasse 1", "private_street": "Musterstrasse 1",
"private_city": "1234 Musterstadt Schweiz", "private_city": "CH-1234 Musterstadt",
"company_name": "Musterfirma", "company_name": "Musterfirma",
"company_street": "Firmastrasse 2", "company_street": "Firmastrasse 2",
"company_city": "5678 Firmastadt Schweiz", "company_city": "CH-5678 Firmastadt",
}, },
template_language=self.user.language, template_language=self.user.language,
fail_silently=ANY, fail_silently=ANY,

View File

@ -5,6 +5,7 @@ from django.test import TestCase
from vbv_lernwelt.core.admin import User from vbv_lernwelt.core.admin import User
from vbv_lernwelt.core.create_default_users import create_default_users 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 ( from vbv_lernwelt.shop.invoice.abacus import (
AbacusInvoiceCreator, AbacusInvoiceCreator,
create_customer_xml, create_customer_xml,
@ -23,6 +24,7 @@ USER_PASSWORD = "testpassword"
class AbacusInvoiceTestCase(TestCase): class AbacusInvoiceTestCase(TestCase):
def setUp(self): def setUp(self):
add_countries(small_set=True)
create_default_users() create_default_users()
def test_create_invoice_xml(self): def test_create_invoice_xml(self):
@ -136,13 +138,14 @@ class AbacusInvoiceTestCase(TestCase):
street_number="32", street_number="32",
postal_code="1719", postal_code="1719",
city="Zumholz", city="Zumholz",
country="209", country_id="CH",
company_name="VBV", invoice_address="org",
company_street="Laupenstrasse", organisation_detail_name="VBV",
company_street_number="10", organisation_street="Laupenstrasse",
company_postal_code="3000", organisation_street_number="10",
company_city="Bern", organisation_postal_code="3000",
company_country="209", organisation_city="Bern",
organisation_country_id="CH",
) )
feuz_checkout_info.created_at = datetime(2024, 2, 15, 8, 33, 12, 0) feuz_checkout_info.created_at = datetime(2024, 2, 15, 8, 33, 12, 0)
@ -158,10 +161,11 @@ class AbacusInvoiceTestCase(TestCase):
"<Email>andreas.feuz@eiger-versicherungen.ch</Email>" "<Email>andreas.feuz@eiger-versicherungen.ch</Email>"
in customer_xml_content in customer_xml_content
) )
assert "<AddressNumber>60000012</AddressNumber>" in customer_xml_content
assert "<Name>Feuz</Name>" in customer_xml_content
assert "<Text>VBV</Text>" in customer_xml_content assert "<Text>VBV</Text>" in customer_xml_content
assert "<Street>Laupenstrasse</Street>" in customer_xml_content
# FIXME refactor country assert "<Country>CH</Country>" in customer_xml_content
assert "<Country>209</Country>" in customer_xml_content
def test_render_customer_xml(self): def test_render_customer_xml(self):
customer_xml = render_customer_xml( customer_xml = render_customer_xml(

View File

@ -1,10 +1,8 @@
import structlog import structlog
from django.conf import settings from django.conf import settings
from django.http import JsonResponse from django.http import JsonResponse
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from sentry_sdk import capture_exception from sentry_sdk import capture_exception
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser 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 ( from vbv_lernwelt.shop.services import (
datatrans_state_to_checkout_state, datatrans_state_to_checkout_state,
get_payment_url, get_payment_url,
init_transaction, init_datatrans_transaction,
InitTransactionException, InitTransactionException,
is_signature_valid, is_signature_valid,
) )
@ -109,7 +107,7 @@ def checkout_vv(request):
return next_step_response(url="/") return next_step_response(url="/")
try: try:
transaction_id = init_transaction( transaction_id = init_datatrans_transaction(
user=request.user, user=request.user,
amount_chf_centimes=product.price, amount_chf_centimes=product.price,
redirect_url_success=checkout_success_url( 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/", "target_url": "https://my.vbv-afa.ch/",
"name": f"{checkout_info.first_name} {checkout_info.last_name}", "name": f"{checkout_info.first_name} {checkout_info.last_name}",
"private_street": f"{checkout_info.street} {checkout_info.street_number}", "private_street": f"{checkout_info.street} {checkout_info.street_number}",
"private_city": f"{checkout_info.postal_code} {checkout_info.city} {checkout_info.country}", "private_city": f"{checkout_info.country_id}-{checkout_info.postal_code} {checkout_info.city}",
"company_name": checkout_info.company_name, "company_name": checkout_info.organisation_detail_name,
"company_street": f"{checkout_info.company_street} {checkout_info.company_street_number}", "company_street": f"{checkout_info.organisation_street} {checkout_info.organisation_street_number}",
"company_city": f"{checkout_info.company_postal_code} {checkout_info.company_city} {checkout_info.company_country}", "company_city": f"{checkout_info.organisation_country_id}-{checkout_info.organisation_postal_code} {checkout_info.organisation_city}",
}, },
template_language=checkout_info.user.language, template_language=checkout_info.user.language,
fail_silently=True, fail_silently=True,