forked from uncloud/uncloud
implement balance getting
This commit is contained in:
parent
1b06d8ee03
commit
6c15d2086e
7 changed files with 53 additions and 65 deletions
|
@ -75,6 +75,7 @@ router.register(r'v2/net/wireguardvpnsizes', netviews.WireGuardVPNSizes, basenam
|
||||||
# Payment related
|
# Payment related
|
||||||
router.register(r'v2/payment/credit-card', payviews.CreditCardViewSet, basename='credit-card')
|
router.register(r'v2/payment/credit-card', payviews.CreditCardViewSet, basename='credit-card')
|
||||||
router.register(r'v2/payment/payment', payviews.PaymentViewSet, basename='payment')
|
router.register(r'v2/payment/payment', payviews.PaymentViewSet, basename='payment')
|
||||||
|
router.register(r'v2/payment/balance', payviews.BalanceViewSet, basename='payment-balance')
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
|
|
@ -68,16 +68,6 @@ class Currency(models.TextChoices):
|
||||||
# USD = 'USD', _('US Dollar')
|
# USD = 'USD', _('US Dollar')
|
||||||
|
|
||||||
|
|
||||||
def get_balance_for_user(user):
|
|
||||||
bills = reduce(
|
|
||||||
lambda acc, entry: acc + entry.total,
|
|
||||||
Bill.objects.filter(owner=user),
|
|
||||||
0)
|
|
||||||
payments = reduce(
|
|
||||||
lambda acc, entry: acc + entry.amount,
|
|
||||||
Payment.objects.filter(owner=user),
|
|
||||||
0)
|
|
||||||
return payments - bills
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# Stripe
|
# Stripe
|
||||||
|
|
23
uncloud_pay/selectors.py
Normal file
23
uncloud_pay/selectors.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
from .models import *
|
||||||
|
|
||||||
|
def get_payments_for_user(user):
|
||||||
|
payments = [ payment.amount for payment in Payment.objects.filter(owner=user) ]
|
||||||
|
|
||||||
|
return sum(payments)
|
||||||
|
|
||||||
|
def get_spendings_for_user(user):
|
||||||
|
orders = Order.objects.filter(owner=user)
|
||||||
|
|
||||||
|
amount = 0
|
||||||
|
for order in orders:
|
||||||
|
amount += order.one_time_price
|
||||||
|
amount += order.recurring_price * order.count_used(when=timezone.now())
|
||||||
|
|
||||||
|
return amount
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def get_balance_for_user(user):
|
||||||
|
return get_payments_for_user(user) - get_spendings_for_user(user)
|
|
@ -5,6 +5,7 @@ from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from .models import *
|
from .models import *
|
||||||
import uncloud_pay.stripe as uncloud_stripe
|
import uncloud_pay.stripe as uncloud_stripe
|
||||||
|
from uncloud import AMOUNT_DECIMALS, AMOUNT_MAX_DIGITS
|
||||||
|
|
||||||
###
|
###
|
||||||
# 2020-12 Checked code
|
# 2020-12 Checked code
|
||||||
|
@ -32,29 +33,13 @@ class PaymentSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
class BalanceSerializer(serializers.Serializer):
|
||||||
|
balance = serializers.DecimalField(max_digits=AMOUNT_MAX_DIGITS, decimal_places=AMOUNT_DECIMALS)
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Unchecked code
|
# Unchecked code
|
||||||
|
|
||||||
###
|
|
||||||
# Payments and Payment Methods.
|
|
||||||
|
|
||||||
|
|
||||||
class UpdatePaymentMethodSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = PaymentMethod
|
|
||||||
fields = ['description', 'primary']
|
|
||||||
|
|
||||||
class ChargePaymentMethodSerializer(serializers.Serializer):
|
|
||||||
amount = serializers.DecimalField(max_digits=10, decimal_places=2)
|
|
||||||
|
|
||||||
class CreatePaymentMethodSerializer(serializers.ModelSerializer):
|
|
||||||
please_visit = serializers.CharField(read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = PaymentMethod
|
|
||||||
fields = ['source', 'description', 'primary', 'please_visit']
|
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# Orders & Products.
|
# Orders & Products.
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
{% extends 'uncloud/base.html' %}
|
|
||||||
|
|
||||||
{% block header %}
|
|
||||||
<style>
|
|
||||||
#content {
|
|
||||||
width: 400px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<div id="content">
|
|
||||||
<h1>Your credit cards registered with Stripe</h1>
|
|
||||||
|
|
||||||
<!-- Stripe form and messages -->
|
|
||||||
<span id="message"></span>
|
|
||||||
|
|
||||||
<p>List of stripe credit cards:
|
|
||||||
<ul>
|
|
||||||
{% for card in cards %}
|
|
||||||
<li>{{ card.brand }} ending in {{ card.last4 }} expiring
|
|
||||||
{{ card.year }}-{{ card.month }}
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
|
@ -21,17 +21,17 @@
|
||||||
terms of my agreement with you.
|
terms of my agreement with you.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- Stripe form and messages -->
|
|
||||||
<span id="message"></span>
|
<span id="message"></span>
|
||||||
|
|
||||||
<div id="card-element"></div>
|
<div id="card-element"></div>
|
||||||
<button type='button' id="card-button"> Save
|
<button type='button' id="card-button">Save</button>
|
||||||
</button>
|
|
||||||
|
|
||||||
<div id="ungleichmessage">The card will be registered with stripe.</div>
|
<div id="ungleichmessage">The card will be registered with stripe.</div>
|
||||||
|
|
||||||
|
<div id="goback" style="display: none;">
|
||||||
|
<a href="{% url 'uncloudindex' %}">Go back to main page</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!-- Enable Stripe from UI elements - standard code -->
|
<!-- Enable Stripe from UI elements - standard code -->
|
||||||
<script>
|
<script>
|
||||||
var stripe = Stripe('{{ stripe_pk }}');
|
var stripe = Stripe('{{ stripe_pk }}');
|
||||||
|
@ -42,11 +42,13 @@
|
||||||
|
|
||||||
var cardButton = document.getElementById('card-button');
|
var cardButton = document.getElementById('card-button');
|
||||||
var messageContainer = document.getElementById('message');
|
var messageContainer = document.getElementById('message');
|
||||||
|
var backmessage = document.getElementById('goback');
|
||||||
var clientSecret = '{{ client_secret }}';
|
var clientSecret = '{{ client_secret }}';
|
||||||
|
|
||||||
cardButton.addEventListener('click', function(ev) {
|
cardButton.addEventListener('click', function(ev) {
|
||||||
document.getElementById("ungleichmessage").innerHTML
|
document.getElementById("ungleichmessage").innerHTML
|
||||||
= "Registering card with Stripe, please wait ..."
|
= "Registering card with Stripe, please wait ...";
|
||||||
|
|
||||||
|
|
||||||
stripe.confirmCardSetup(
|
stripe.confirmCardSetup(
|
||||||
clientSecret,
|
clientSecret,
|
||||||
|
@ -64,8 +66,12 @@
|
||||||
// Return to API on success.
|
// Return to API on success.
|
||||||
document.getElementById("ungleichmessage").innerHTML
|
document.getElementById("ungleichmessage").innerHTML
|
||||||
= "Registered credit card with Stripe."
|
= "Registered credit card with Stripe."
|
||||||
|
|
||||||
|
backmessage.style.display = "block";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -24,12 +24,15 @@ import logging
|
||||||
|
|
||||||
from .models import *
|
from .models import *
|
||||||
from .serializers import *
|
from .serializers import *
|
||||||
|
from .selectors import *
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from vat_validator import sanitize_vat
|
from vat_validator import sanitize_vat
|
||||||
import uncloud_pay.stripe as uncloud_stripe
|
import uncloud_pay.stripe as uncloud_stripe
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# 2020-12 checked code
|
# 2020-12 checked code
|
||||||
|
|
||||||
|
@ -75,6 +78,16 @@ class PaymentViewSet(viewsets.ModelViewSet):
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return Payment.objects.filter(owner=self.request.user)
|
return Payment.objects.filter(owner=self.request.user)
|
||||||
|
|
||||||
|
class BalanceViewSet(viewsets.ViewSet):
|
||||||
|
permission_classes = [permissions.IsAuthenticated]
|
||||||
|
|
||||||
|
def list(self, request):
|
||||||
|
serializer = BalanceSerializer(data={
|
||||||
|
'balance': get_balance_for_user(self.request.user)
|
||||||
|
})
|
||||||
|
serializer.is_valid()
|
||||||
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
# Payments and Payment Methods.
|
# Payments and Payment Methods.
|
||||||
|
|
Loading…
Reference in a new issue