diff --git a/apps/authentication/admin.py b/apps/authentication/admin.py index d5ddb58d7..ef0dd0663 100644 --- a/apps/authentication/admin.py +++ b/apps/authentication/admin.py @@ -48,7 +48,6 @@ class OnlineUserAdmin(UserAdmin, VersionAdmin): "mark_rules_accepted", "rfid", "nickname", - "saldo", "website", ) }, @@ -68,7 +67,7 @@ class OnlineUserAdmin(UserAdmin, VersionAdmin): ) filter_horizontal = ("groups", "user_permissions") search_fields = ("first_name", "last_name", "username", "ntnu_username") - readonly_fields = ("mark_rules_accepted", "saldo", "auth0_subject") + readonly_fields = ("mark_rules_accepted", "auth0_subject") def is_member(self, instance: OnlineUser): return instance.is_member diff --git a/apps/authentication/api/serializers/user_data.py b/apps/authentication/api/serializers/user_data.py index 3e71140e6..7ccf7e328 100644 --- a/apps/authentication/api/serializers/user_data.py +++ b/apps/authentication/api/serializers/user_data.py @@ -22,13 +22,7 @@ RuleAcceptanceSerializer, SuspensionSerializer, ) -from apps.payment.models import ( - Payment, - PaymentDelay, - PaymentPrice, - PaymentRelation, - PaymentTransaction, -) +from apps.payment.models import Payment, PaymentDelay, PaymentPrice, PaymentRelation from apps.profiles.serializers import PrivacySerializer from apps.webshop.models import Order as WebshopOrder from apps.webshop.models import OrderLine as WebshopOrderLine @@ -155,21 +149,6 @@ class Meta: fields = ("group_name", "added", "is_on_leave", "is_retired", "roles") -class PaymentTransactionSerializer(serializers.ModelSerializer): - items = serializers.SerializerMethodField() - description = serializers.SerializerMethodField() - - def get_items(self, obj: PaymentTransaction): - return obj.get_receipt_items() - - def get_description(self, obj: PaymentTransaction): - return obj.get_receipt_description() - - class Meta: - model = PaymentTransaction - fields = ("amount", "used_stripe", "datetime", "status", "description", "items") - - class PaymentPriceSerializer(serializers.ModelSerializer): class Meta: model = PaymentPrice @@ -278,9 +257,6 @@ class UserDataSerializer(serializers.ModelSerializer): payment_relations = PaymentRelationSerializer( many=True, source="paymentrelation_set" ) - payment_transactions = PaymentTransactionSerializer( - many=True, source="paymenttransaction_set" - ) # Purchases orderline_set = WebshopOrderLineSerializer(many=True) # Marks @@ -328,13 +304,10 @@ class Meta: "allergies", "linkedin", "rfid", - "saldo", "field_of_study", "phone_number", "gender", "github", - "rfid", - "saldo", "website", "year", "zip_code", @@ -375,7 +348,6 @@ class Meta: # Payments "payment_delays", "payment_relations", - "payment_transactions", # Purchases "orderline_set", # Approval diff --git a/apps/authentication/models.py b/apps/authentication/models.py index b005bac90..d5ba707a1 100644 --- a/apps/authentication/models.py +++ b/apps/authentication/models.py @@ -17,7 +17,6 @@ from apps.authentication.constants import FieldOfStudyType, GroupType, RoleType from apps.authentication.validators import validate_rfid from apps.gallery.models import ResponsiveImage -from apps.payment import status as PaymentStatus from apps.permissions.models import ObjectPermissionModel logger = logging.getLogger(__name__) @@ -226,15 +225,6 @@ def member(self): return None return Membership.objects.get(username=self.ntnu_username.lower()) - @property - def saldo(self) -> int: - value = ( - self.paymenttransaction_set.filter(status=PaymentStatus.DONE) - .aggregate(coins=models.Sum("amount")) - .get("coins") - ) - return value if value is not None else 0 - @property def year(self): start_year = get_start_of_field_of_study(self.field_of_study) diff --git a/apps/payment/admin.py b/apps/payment/admin.py index 247a539f9..31bb72b64 100644 --- a/apps/payment/admin.py +++ b/apps/payment/admin.py @@ -10,7 +10,6 @@ PaymentPrice, PaymentReceipt, PaymentRelation, - PaymentTransaction, ) @@ -84,13 +83,7 @@ class PaymentReceiptAdmin(admin.ModelAdmin): search_fields = ["receipt_id"] -class PaymentTransactionAdmin(VersionAdmin): - model = PaymentTransaction - list_display = ("__str__", "user", "datetime", "amount", "used_stripe", "source") - - admin.site.register(PaymentReceipt, PaymentReceiptAdmin) admin.site.register(Payment, PaymentAdmin) admin.site.register(PaymentRelation, PaymentRelationAdmin) admin.site.register(PaymentDelay, PaymentDelayAdmin) -admin.site.register(PaymentTransaction, PaymentTransactionAdmin) diff --git a/apps/payment/migrations/0038_delete_paymenttransaction.py b/apps/payment/migrations/0038_delete_paymenttransaction.py new file mode 100644 index 000000000..6bb47ae48 --- /dev/null +++ b/apps/payment/migrations/0038_delete_paymenttransaction.py @@ -0,0 +1,16 @@ +# Generated by Django 5.0.4 on 2024-04-07 10:02 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("payment", "0037_alter_payment_payment_type"), + ] + + operations = [ + migrations.DeleteModel( + name="PaymentTransaction", + ), + ] diff --git a/apps/payment/models.py b/apps/payment/models.py index 96ee7920f..ba08030fe 100644 --- a/apps/payment/models.py +++ b/apps/payment/models.py @@ -19,7 +19,6 @@ from apps.payment import status from .mixins import PaymentMixin, ReceiptMixin -from .transaction_constants import TransactionSource User = settings.AUTH_USER_MODEL @@ -320,89 +319,6 @@ class Meta: ordering = ("active", "valid_to") -class TransactionManager(models.Manager): - def aggregate_coins(self, user: User) -> int: - """ - :return: The aggregated amount of coins in a users wallet. - """ - value = ( - self.filter(user=user, status=status.DONE) - .aggregate(coins=models.Sum("amount")) - .get("coins") - ) - return value if value is not None else 0 - - -class PaymentTransaction(ReceiptMixin, StripeMixin, models.Model): - """ - A transaction for a User - The set of all transactions for a user defines the amount of 'coins' a user has. - """ - - objects = TransactionManager() - - user = models.ForeignKey(User, on_delete=models.CASCADE) - amount = models.IntegerField(null=True, blank=True) - """Amount in NOK""" - source = models.CharField(max_length=64, choices=TransactionSource.ALL_CHOICES) - """ Origin of the transaction, such as purchases in Nibble or additions from Stripe """ - datetime = models.DateTimeField(auto_now_add=True) - - @property - def used_stripe(self): - return self.source == TransactionSource.STRIPE - - def get_receipt_timestamp(self) -> timezone.datetime: - return self.datetime - - def get_receipt_subject(self) -> str: - return f"[Kvittering] {self.get_receipt_description()}" - - def get_receipt_description(self) -> str: - if self.source == TransactionSource.STRIPE: - return "Saldoinnskudd på online.ntnu.no" - elif self.source == TransactionSource.TRANSFER: - return "Overføring av saldo til annen bruker på online.ntnu.no" - elif self.source == TransactionSource.CASH: - return "Innskudd av kontanter på online.ntnu.no" - elif self.source == TransactionSource.SHOP: - return "Kjøp i Onlinekiosken" - - def get_receipt_items(self): - if self.source == TransactionSource.STRIPE: - return [{"name": "Påfyll av saldo", "price": self.amount, "quantity": 1}] - elif self.source == TransactionSource.TRANSFER: - return [ - {"name": "Overføring av saldo", "price": self.amount, "quantity": 1} - ] - elif self.source == TransactionSource.CASH: - return [ - {"name": "Påfyll av kontanter", "price": self.amount, "quantity": 1} - ] - elif self.source == TransactionSource.SHOP: - if hasattr(self, "shop_order_line"): - return self.shop_order_line.get_order_descriptions() - else: - raise ValueError( - "Transaction for a shop purchase is not connected to an OrderLine" - ) - - def get_receipt_from_email(self): - return settings.EMAIL_TRIKOM - - def get_receipt_to_user(self): - return self.user - - def __str__(self): - return f"{self.user} - {self.amount} ({self.datetime})" - - class Meta: - ordering = ["-datetime"] - verbose_name = _("transaksjon") - verbose_name_plural = _("transaksjoner") - default_permissions = ("add", "change", "delete") - - class PaymentReceipt(models.Model): """Transaction receipt""" diff --git a/apps/payment/serializers.py b/apps/payment/serializers.py index f5419ef59..bcdaeeba9 100644 --- a/apps/payment/serializers.py +++ b/apps/payment/serializers.py @@ -1,20 +1,11 @@ import logging import stripe -from django.conf import settings from rest_framework import serializers from rest_framework.serializers import ValidationError from apps.payment import status -from apps.payment.models import ( - Payment, - PaymentDelay, - PaymentPrice, - PaymentRelation, - PaymentTransaction, -) - -from .transaction_constants import TransactionSource +from apps.payment.models import Payment, PaymentDelay, PaymentPrice, PaymentRelation logger = logging.getLogger(__name__) @@ -267,195 +258,3 @@ class Meta: "payment", "payment_price", ) - - -class PaymentTransactionReadOnlySerializer(serializers.ModelSerializer): - items = serializers.SerializerMethodField() - description = serializers.SerializerMethodField() - - def get_items(self, obj: PaymentTransaction): - return obj.get_receipt_items() - - def get_description(self, obj: PaymentTransaction): - return obj.get_receipt_description() - - class Meta: - model = PaymentTransaction - fields = ( - "id", - "amount", - "used_stripe", - "datetime", - "status", - "payment_intent_secret", - "description", - "items", - "source", - ) - read_only = True - - -class PaymentTransactionCreateSerializer(serializers.ModelSerializer): - user = serializers.HiddenField(default=serializers.CurrentUserDefault()) - payment_method_id = serializers.CharField(write_only=True) - source = serializers.HiddenField(default=TransactionSource.STRIPE) - amount = serializers.IntegerField(required=True) - - def validate_amount(self, amount): - valid_amounts = [100, 200, 300, 500, 800, 1000] - if amount not in valid_amounts: - raise ValidationError(f"{amount} er ikke en gyldig betalingspris") - - return amount - - def create(self, validated_data): - request = self.context.get("request") - - amount = validated_data.get("amount") - payment_method_id = validated_data.pop("payment_method_id") - - logger.info(f"User: {request.user} attempting to add {amount} to saldo") - - transaction: PaymentTransaction = super().create( - {**validated_data, "status": status.PENDING} - ) - - try: - """Use Trikom key for additions to user saldo""" - stripe_private_key = settings.STRIPE_PRIVATE_KEYS["trikom"] - - intent = stripe.PaymentIntent.create( - payment_method=payment_method_id, - amount=amount - * 100, # Price is multiplied with 100 because the amount is in øre - currency="nok", - confirmation_method="manual", - confirm=True, - description=f"Saldo deposit - {request.user.email}", - api_key=stripe_private_key, - ) - - # If the payment needs more validation by Stripe or the bank - if ( - intent.status == "requires_source_action" - and intent.next_action.type == "use_stripe_sdk" - ): - transaction.status = status.PENDING - transaction.payment_intent_secret = intent.client_secret - - elif intent.status == "succeeded": - transaction.status = status.SUCCEEDED - - else: - logger.error( - f"Payment intent returned an invalid status: {intent.status}" - ) - raise ValidationError( - "Det skjedde noe galt under behandlingen av betalingen " - ) - - transaction.stripe_id = intent.id - transaction.save() - - return transaction - - except stripe.error.CardError as err: - error = err.json_body.get("error", {}) - logger.error( - f"Stripe charge for {request.user} failed with card_error: {error}" - ) - raise ValidationError(error) - - except stripe.error.StripeError as error: - logger.error(f"An error occurred during the Stripe charge: {error}") - raise ValidationError(error) - - class Meta: - model = PaymentTransaction - fields = ( - "id", - "payment_method_id", - "payment_intent_secret", - "amount", - "used_stripe", - "user", - "status", - "datetime", - "source", - ) - read_only_fields = ("id", "payment_intent_secret", "status", "datetime") - - -class PaymentTransactionUpdateSerializer(serializers.ModelSerializer): - payment_intent_id = serializers.CharField( - write_only=True, required=True, allow_blank=False - ) - - def update(self, instance: PaymentTransaction, validated_data): - # Update should only be used to confirm transactions. PENDING is the first stage of a payment. - if instance.status != status.PENDING: - raise ValidationError("Denne transaksjonen er allerede betalt og bekreftet") - - # Remove data, as we only want to use it to potentially write data derived from it - payment_intent_id = validated_data.pop("payment_intent_id") - - try: - """Use Trikom key for additions to user saldo""" - stripe.api_key = settings.STRIPE_PRIVATE_KEYS["trikom"] - - intent = stripe.PaymentIntent.confirm(payment_intent_id) - - # If the status is still not confirmed we update the transaction with a new secret key to handle. - if ( - intent.status == "requires_source_action" - and intent.next_action.type == "use_stripe_sdk" - ): - return super().update( - instance, - {**validated_data, "payment_intent_secret": intent.client_secret}, - ) - # If the payment is successfully confirmed we update the status of the transaction to SUCCEEDED. - elif intent.status == "succeeded": - return super().update( - instance, {**validated_data, "status": status.SUCCEEDED} - ) - - else: - logger.error( - f"Payment intent returned an invalid status: {intent.status}" - ) - raise ValidationError( - "Det skjedde noe galt under behandlingen av betalingsbekreftelsen " - ) - - except stripe.error.CardError as error: - logger.error( - f"An error occurred during confirmation of " - f"PaymentTransaction: {instance.id} by user: {instance.user}", - error, - ) - raise ValidationError( - "Det skjedde en feil under bekreftelsen av betalingen." - ) - - class Meta: - model = PaymentTransaction - fields = ( - "payment_intent_id", - "id", - "payment_intent_secret", - "amount", - "status", - "used_stripe", - "datetime", - "source", - ) - read_only_fields = ( - "id", - "payment_intent_secret", - "amount", - "status", - "used_stripe", - "datetime", - "source", - ) diff --git a/apps/payment/signals.py b/apps/payment/signals.py index 2924853c3..0f3d222fa 100644 --- a/apps/payment/signals.py +++ b/apps/payment/signals.py @@ -1,5 +1,3 @@ -from typing import Union - from django.contrib.contenttypes.models import ContentType from django.db.models import Q from django.db.models.signals import post_save, pre_save @@ -8,7 +6,7 @@ from utils.disable_for_loaddata import disable_for_loaddata from . import status -from .models import PaymentReceipt, PaymentRelation, PaymentTransaction +from .models import PaymentReceipt, PaymentRelation @receiver(signal=pre_save, sender=PaymentRelation) @@ -23,27 +21,9 @@ def handle_payment_relation_status_change(sender, instance: PaymentRelation, **k instance.status = status.REMOVED -@receiver(signal=pre_save, sender=PaymentTransaction) -def handle_payment_transaction_status_change( - sender, instance: PaymentTransaction, **kwargs -): - # When a payment succeeds, it should be stored to the DB - if instance.status == status.SUCCEEDED: - # Pass the transaction to the next step, which is DONE - instance.status = status.DONE - - # Handle when a transaction is being refunded by Stripe - if instance.status == status.REFUNDED: - # Pass transaction to the next strip, which is REMOVED - instance.status = status.REMOVED - - @receiver(signal=post_save, sender=PaymentRelation) -@receiver(signal=post_save, sender=PaymentTransaction) @disable_for_loaddata -def send_receipt_after_payment( - sender, instance: Union[PaymentRelation, PaymentTransaction], **kwargs -): +def send_receipt_after_payment(sender, instance: PaymentRelation, **kwargs): content_type = ContentType.objects.get_for_model(instance) receipt_exists = PaymentReceipt.objects.filter( Q(object_id=instance.id) & Q(content_type=content_type) diff --git a/apps/payment/tests/api_tests.py b/apps/payment/tests/api_tests.py index 3f91119e8..779d17f4d 100644 --- a/apps/payment/tests/api_tests.py +++ b/apps/payment/tests/api_tests.py @@ -465,199 +465,6 @@ def test_user_cannot_refund_after_the_event_has_started(self): ) -@stripe_test -class PaymentTransactionTestCase(APITestCase): - def setUp(self): - self.user = generate_user(username="test_user") - self.client.force_authenticate(user=self.user) - - self.url = reverse("payment_transactions-list") - self.id_url = lambda _id: self.url + str(_id) + "/" - date_next_year = timezone.now() + timezone.timedelta(days=366) - self.mock_card = { - "number": "4000000000003055", - "exp_month": 12, - "exp_year": date_next_year.year, - "cvc": "123", - } - self.mock_3d_secure_card = { - "number": "4000000000003220", - "exp_month": 12, - "exp_year": date_next_year.year, - "cvc": "123", - } - stripe.api_key = settings.STRIPE_PUBLIC_KEYS["trikom"] - self.payment_method = stripe.PaymentMethod.create( - type="card", card=self.mock_card - ) - self.secure_payment_method = stripe.PaymentMethod.create( - type="card", card=self.mock_3d_secure_card - ) - self.amount = 100 - - def test_user_has_access_to_view_transactions(self): - response = self.client.get(self.url) - - self.assertEqual(response.status_code, status.HTTP_200_OK) - - def test_unauthenticated_clients_cannot_access_transactions(self): - self.client.force_authenticate(user=None) - response = self.client.get(self.url) - - self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) - self.assertEqual( - response.json().get("detail"), "Manglende autentiseringsinformasjon." - ) - - def test_user_can_create_a_transaction_with_a_regular_card(self): - response = self.client.post( - self.url, - {"amount": self.amount, "payment_method_id": self.payment_method.id}, - ) - - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - self.assertEqual(response.json().get("status"), payment_status.DONE) - - @mock_payment_intent_confirm() - def test_initiating_a_3d_secure_transaction_results_in_a_pending_transaction( - self, _ - ): - response = self.client.post( - self.url, - {"amount": self.amount, "payment_method_id": self.secure_payment_method.id}, - ) - - current_payment_status = response.json().get("status") - payment_intent_secret = response.json().get("payment_intent_secret") - - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - self.assertEqual(current_payment_status, payment_status.PENDING) - self.assertIsNotNone(current_payment_status, payment_intent_secret) - - @mock_payment_intent_confirm() - def test_user_can_complete_a_3d_secure_transaction(self, _): - initial_response = self.client.post( - self.url, - {"amount": self.amount, "payment_method_id": self.secure_payment_method.id}, - ) - - self.assertEqual(initial_response.status_code, status.HTTP_201_CREATED) - - """ - Handling a payment_intent_secret _has_ to be done on a client via Stripe.js. - Stripe will prompt the user with a modal requiring interaction via something like BankID. - The response has been mocked in 3D secure tests, since it cannot be done with regular unit testing. - https://stripe.com/docs/payments/payment-intents/quickstart#handling-next-actions - """ - transaction_id = initial_response.json().get("id") - confirm_response = self.client.patch( - self.id_url(transaction_id), - { - "payment_intent_id": "--some-fake-id--", - # Fake id works since actual validation has been disabled by the mock_payment_intent_confirm decorator - }, - ) - - current_payment_status = confirm_response.json().get("status") - - self.assertEqual(confirm_response.status_code, status.HTTP_200_OK) - self.assertEqual(current_payment_status, payment_status.DONE) - - def test_user_saldo_is_updated_when_a_transaction_is_confirmed(self): - starting_saldo = self.user.saldo - expected_saldo = starting_saldo + self.amount - - # Use existing test to to the hard work, since it completely relies on the things done in it. - self.test_user_can_complete_a_3d_secure_transaction() - - self.user.refresh_from_db() - - self.assertEqual(self.user.saldo, expected_saldo) - - def test_user_saldo_is_updated_when_a_transaction_is_done(self): - starting_saldo = self.user.saldo - expected_saldo = starting_saldo + self.amount - - response = self.client.post( - self.url, - {"amount": self.amount, "payment_method_id": self.payment_method.id}, - ) - - self.user.refresh_from_db() - - self.assertEqual(self.user.saldo, expected_saldo) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - - @mock_payment_intent_confirm() - def test_user_saldo_is_not_updated_when_a_transaction_is_pending(self, _): - starting_saldo = self.user.saldo - saldo_id_succeeded = starting_saldo + self.amount - - response = self.client.post( - self.url, - {"amount": self.amount, "payment_method_id": self.secure_payment_method.id}, - ) - - self.user.refresh_from_db() - - self.assertEqual(self.user.saldo, starting_saldo) - self.assertNotEqual(self.user.saldo, saldo_id_succeeded) - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - - def test_user_cannot_create_a_transaction_with_wrong_price(self): - wrong_amount = 666 - - response = self.client.post( - self.url, - {"amount": wrong_amount, "payment_method_id": self.payment_method.id}, - ) - - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertEqual( - response.json().get("amount"), - [f"{wrong_amount} er ikke en gyldig betalingspris"], - ) - - def test_transaction_fails_without_payment_method_id(self): - response = self.client.post(self.url, {"amount": self.amount}) - - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertEqual( - response.json().get("payment_method_id"), ["Dette feltet er påkrevd."] - ) - - def test_event_payment_fails_with_fake_payment_method_id(self): - fake_payment_method_id = "--fake-token--" - - response = self.client.post( - self.url, - {"amount": self.amount, "payment_method_id": fake_payment_method_id}, - ) - - self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) - self.assertIn( - f"No such PaymentMethod: '{fake_payment_method_id}'", response.json()[0] - ) - - def test_user_cannot_delete_transactions(self): - create_response = self.client.post( - self.url, - {"amount": self.amount, "payment_method_id": self.payment_method.id}, - ) - - self.assertEqual(create_response.status_code, status.HTTP_201_CREATED) - - transaction_id = create_response.json().get("id") - - delete_response = self.client.delete(self.id_url(transaction_id)) - - self.assertEqual(delete_response.status_code, status.HTTP_403_FORBIDDEN) - self.assertEqual( - delete_response.json().get("message"), - "Du kan ikke slette eksisterende transaksjoner", - ) - - @stripe_test class PaymentDelayTestCase(APITestCase): def setUp(self): diff --git a/apps/payment/transaction_constants.py b/apps/payment/transaction_constants.py deleted file mode 100644 index 1e6dcef31..000000000 --- a/apps/payment/transaction_constants.py +++ /dev/null @@ -1,12 +0,0 @@ -class TransactionSource: - STRIPE = "stripe" - CASH = "cash" - SHOP = "shop" - TRANSFER = "transfer" - - ALL_CHOICES = ( - (STRIPE, "Stripe"), - (CASH, "Kontant"), - (SHOP, "Kiosk"), - (TRANSFER, "Overføring"), - ) diff --git a/apps/payment/urls.py b/apps/payment/urls.py index 70ba456cd..a47e50ddc 100644 --- a/apps/payment/urls.py +++ b/apps/payment/urls.py @@ -9,11 +9,6 @@ router.register( "payment/relations", views.PaymentRelationViewSet, basename="payment_relations" ) -router.register( - "payment/transactions", - views.PaymentTransactionViewSet, - basename="payment_transactions", -) router.register( "payment/prices", views.PaymentPriceReadOnlyViewSet, basename="payment_prices" ) diff --git a/apps/payment/views.py b/apps/payment/views.py index 70968b3b1..84de5c352 100644 --- a/apps/payment/views.py +++ b/apps/payment/views.py @@ -10,21 +10,13 @@ from apps.common.rest_framework.mixins import MultiSerializerMixin from apps.payment import status as payment_status -from apps.payment.models import ( - PaymentDelay, - PaymentPrice, - PaymentRelation, - PaymentTransaction, -) +from apps.payment.models import PaymentDelay, PaymentPrice, PaymentRelation from apps.payment.serializers import ( PaymentDelayReadOnlySerializer, PaymentPriceReadOnlySerializer, PaymentRelationCreateSerializer, PaymentRelationReadOnlySerializer, PaymentRelationUpdateSerializer, - PaymentTransactionCreateSerializer, - PaymentTransactionReadOnlySerializer, - PaymentTransactionUpdateSerializer, ) logger = logging.getLogger(__name__) @@ -112,29 +104,3 @@ class PaymentPriceReadOnlyViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = (permissions.IsAuthenticated,) serializer_class = PaymentPriceReadOnlySerializer queryset = PaymentPrice.objects.all() - - -class PaymentTransactionViewSet(MultiSerializerMixin, viewsets.ModelViewSet): - """ - A user should be allowed to view their transactions. - Transactions are created with Stripe payment intents. - Transactions are only updated to confirm pending payment intents. - A use should not be able to delete a transaction. - """ - - permission_classes = (permissions.IsAuthenticated,) - serializer_classes = { - "read": PaymentTransactionReadOnlySerializer, - "create": PaymentTransactionCreateSerializer, - "update": PaymentTransactionUpdateSerializer, - } - - def get_queryset(self): - user = self.request.user - return PaymentTransaction.objects.filter(user=user) - - def destroy(self, request, *args, **kwargs): - return Response( - {"message": "Du kan ikke slette eksisterende transaksjoner"}, - status.HTTP_403_FORBIDDEN, - ) diff --git a/apps/profiles/serializers.py b/apps/profiles/serializers.py index 5457d6d60..b2fd55cc2 100644 --- a/apps/profiles/serializers.py +++ b/apps/profiles/serializers.py @@ -43,7 +43,6 @@ class Meta: "mark_rules_accepted", "gender", "bio", - "saldo", "is_committee", "is_member", "image", @@ -56,7 +55,6 @@ class Meta: "field_of_study", "started_date", "compiled", - "saldo", )