Coverage for payments/serializers.py: 74%
124 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-13 14:00 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-13 14:00 -0600
1from rest_framework import serializers
2from rest_polymorphic.serializers import PolymorphicSerializer
3from app.stripe.actions import Stripe
4from accounting.models import ProductCharge
5from memberships.models import Membership
6from memberships.serializers import BasicMembershipSerializer
7from .models import Payment, PaymentIntent, ManualPayment, PaymentAllocation, PaymentAllocationExport
10class PaymentSerializer(serializers.ModelSerializer):
11 class Meta:
12 model = Payment
13 read_only_fields = ["random_slug", "created_at"]
14 fields = read_only_fields + ["membership", "amount", "concept"]
16 def to_representation(self, instance):
17 representation = super(PaymentSerializer, self).to_representation(instance)
18 membership_slug = representation.get("membership")
19 membership = Membership.objects.get(random_slug=membership_slug)
20 serializer = BasicMembershipSerializer(instance=membership)
21 representation["membership"] = serializer.data
22 return representation
25class PaymentAllocationSerializer(serializers.ModelSerializer):
26 class Meta:
27 model = PaymentAllocation
28 read_only_fields = ["random_slug", "created_at"]
29 fields = read_only_fields + ["product_charge", "amount"]
32class PaymentIntentSerializer(serializers.ModelSerializer):
33 payment_allocations = PaymentAllocationSerializer(many=True, required=False)
35 class Meta:
36 model = PaymentIntent
37 read_only_fields = ["random_slug", "stripe_pi_id", "created_at", "stripe_pi_id"]
38 fields = read_only_fields + ["membership", "payment_method", "amount", "concept", "payment_allocations"]
40 def _make_stripe_payment_intent(self, membership, amount, payment_method):
41 try:
42 pi_id = Stripe(membership=membership).create_payment_intent(
43 amount=int(amount * 100), payment_method=payment_method
44 )
45 except Exception as e:
46 raise serializers.ValidationError(e)
48 return pi_id
50 def create(self, validated_data):
51 membership = validated_data.pop("membership")
52 payment_method = validated_data.pop("payment_method")
53 amount = validated_data.pop("amount")
54 payment_allocations = validated_data.get("payment_allocations", None)
56 for allocation in payment_allocations:
57 product_charge = allocation.get("product_charge")
58 if (product_charge.paid_amount + allocation.get("amount")) > product_charge.amount: 58 ↛ 59line 58 didn't jump to line 59, because the condition on line 58 was never true
59 raise serializers.ValidationError({"detail": "No se puede pagar un monto mayor al pendiente"})
61 pi_id = self._make_stripe_payment_intent(membership, amount, payment_method)
63 payment_intent = PaymentIntent.objects.create(
64 organization=membership.organization,
65 membership=membership,
66 amount=amount,
67 stripe_pi_id=pi_id,
68 payment_method=payment_method,
69 )
71 for allocation in payment_allocations:
72 PaymentAllocation.objects.create(
73 payment=payment_intent, product_charge=allocation.get("product_charge"), amount=allocation.get("amount")
74 )
76 return payment_intent
78 def to_representation(self, instance):
79 representation = super(PaymentIntentSerializer, self).to_representation(instance)
80 membership_slug = representation.get("membership")
81 membership = Membership.objects.get(random_slug=membership_slug)
82 serializer = BasicMembershipSerializer(instance=membership)
83 representation["membership"] = serializer.data
84 return representation
87class MemberPaymentIntentSerializer(PaymentIntentSerializer):
88 product_charges = serializers.PrimaryKeyRelatedField(
89 many=True, write_only=True, queryset=ProductCharge.objects.all()
90 )
92 class Meta(PaymentIntentSerializer.Meta):
93 read_only_fields = ["random_slug", "stripe_pi_id", "created_at", "stripe_pi_id"]
94 fields = read_only_fields + [
95 "membership",
96 "payment_method",
97 "concept",
98 "payment_allocations",
99 "product_charges",
100 ]
101 extra_kwargs = {"product_charges": {"write_only": True}}
103 def create(self, validated_data):
104 membership = validated_data.pop("membership")
105 payment_method = validated_data.pop("payment_method")
106 product_charges = validated_data.pop("product_charges")
108 total_amount = sum(product_charge.amount - product_charge.paid_amount for product_charge in product_charges)
110 if total_amount == 0:
111 raise serializers.ValidationError({"detail": "El monto a pagar no puede ser 0"})
113 pi_id = self._make_stripe_payment_intent(membership, total_amount, payment_method)
115 payment_intent = PaymentIntent.objects.create(
116 organization=membership.organization,
117 membership=membership,
118 amount=total_amount,
119 stripe_pi_id=pi_id,
120 payment_method=payment_method,
121 )
123 for product_charge in product_charges:
124 PaymentAllocation.objects.create(
125 payment=payment_intent,
126 product_charge=product_charge,
127 amount=product_charge.amount - product_charge.paid_amount,
128 )
130 return payment_intent
133class ManualPaymentSerializer(serializers.ModelSerializer):
134 payment_allocations = PaymentAllocationSerializer(many=True, required=False)
136 class Meta:
137 model = ManualPayment
138 read_only_fields = ["random_slug", "created_at"]
139 fields = read_only_fields + [
140 "membership",
141 "payment_method_type",
142 "date",
143 "amount",
144 "concept",
145 "reference",
146 "payment_allocations",
147 ]
149 def create(self, validated_data):
150 membership = validated_data.get("membership")
151 payment_allocations = validated_data.pop("payment_allocations", None)
153 for allocation in payment_allocations:
154 product_charge = allocation.get("product_charge")
155 if (product_charge.paid_amount + allocation.get("amount")) > product_charge.amount: 155 ↛ 156line 155 didn't jump to line 156, because the condition on line 155 was never true
156 raise serializers.ValidationError({"detail": "No se puede pagar un monto mayor al pendiente"})
158 validated_data["organization"] = membership.organization
160 manual_payment = ManualPayment.objects.create(**validated_data)
162 for allocation in payment_allocations:
163 PaymentAllocation.objects.create(
164 payment=manual_payment, product_charge=allocation.get("product_charge"), amount=allocation.get("amount")
165 )
167 return manual_payment
169 def to_representation(self, instance):
170 representation = super(ManualPaymentSerializer, self).to_representation(instance)
171 membership_slug = representation.get("membership")
172 membership = Membership.objects.get(random_slug=membership_slug)
173 serializer = BasicMembershipSerializer(instance=membership)
174 representation["membership"] = serializer.data
175 return representation
178class PaymentPolymorphicSerializer(PolymorphicSerializer):
179 """
180 Polymorphic serializer for Payment objects
181 """
183 model_serializer_mapping = {
184 PaymentIntent: PaymentIntentSerializer,
185 ManualPayment: ManualPaymentSerializer,
186 }
189class PaymentAllocationExportSerializer(serializers.ModelSerializer):
190 """
191 Serializer for PaymentAllocationExport
192 """
194 class Meta:
195 model = PaymentAllocationExport
196 read_only_fields = ["random_slug", "created_at", "export_file"]
197 fields = read_only_fields + ["from_date", "to_date"]
200class PublicPaymentIntentSerializer(PaymentIntentSerializer):
201 product_charges = serializers.PrimaryKeyRelatedField(
202 many=True, write_only=True, queryset=ProductCharge.objects.all()
203 )
204 cs_url = serializers.URLField()
206 class Meta(PaymentIntentSerializer.Meta):
207 read_only_fields = ["random_slug", "created_at", "stripe_cs_id", "cs_url"]
208 fields = read_only_fields + [
209 "success_url",
210 "cancel_url",
211 "concept",
212 "payment_allocations",
213 "product_charges",
214 ]
215 extra_kwargs = {"product_charges": {"write_only": True}}
217 def create(self, validated_data):
218 payment_method = validated_data.pop("payment_method")
219 product_charges = validated_data.pop("product_charges")
221 total_amount = sum(product_charge.amount - product_charge.paid_amount for product_charge in product_charges)
223 if total_amount == 0:
224 raise serializers.ValidationError({"detail": "El monto a pagar no puede ser 0"})
226 # pi_id = self._make_stripe_payment_intent(membership, total_amount, payment_method)
228 payment_intent = PaymentIntent.objects.create(
229 organization=product_charges.first().organization,
230 amount=total_amount,
231 # stripe_pi_id=pi_id,
232 payment_method=payment_method,
233 )
235 for product_charge in product_charges:
236 PaymentAllocation.objects.create(
237 payment=payment_intent,
238 product_charge=product_charge,
239 amount=product_charge.amount - product_charge.paid_amount,
240 )
242 return payment_intent