initial commit
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
{% load static %}
|
||||
<html>
|
||||
<head>
|
||||
<title>Wallet Monitor</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="{% static 'Skeleton/css/normalize.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'Skeleton/css/skeleton.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/style.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/topnav.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/accordion.css' %}">
|
||||
</head>
|
||||
<body>
|
||||
{% if user.is_authenticated %}
|
||||
<nav class="topnav">
|
||||
<a href="/monitor">Monitor</a>
|
||||
<a href="/transactions/show">Transactions</a>
|
||||
<a class="right" href="/accounts/logout/">Logout</a>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,10 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-box">
|
||||
<h2>Success!</h2>
|
||||
|
||||
<p>Now you can <a href="{% url 'login' %}">Login</a></p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
Hello {{ user.username }},
|
||||
|
||||
you have registered at {{ site }}
|
||||
|
||||
If this was not you, please ignore this email!
|
||||
|
||||
If you want to activate your account at https://{{ site }}, please click on this link:
|
||||
|
||||
{% autoescape off %}
|
||||
Please click on the link to confirm your registration, https://{{ site }}{% url 'django_registration_activate' activation_key=activation_key %}
|
||||
{% endautoescape %}
|
||||
|
||||
All the best!
|
||||
|
||||
The team at {{ site }}
|
||||
|
||||
PS: this is an automated E-Mail, please do not reply.
|
||||
You can contact us at info@{{ site }}
|
||||
@@ -0,0 +1 @@
|
||||
Confirm your registration for {{ site }}
|
||||
@@ -0,0 +1,11 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-box">
|
||||
<h2>Something went wrong.</h2>
|
||||
|
||||
<p>Perhaps you have confirmed already?</p>
|
||||
|
||||
<p>Please try to <a href="{% url 'login' %}">Login</a></p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,9 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-box">
|
||||
<h2>Success!</h2>
|
||||
|
||||
<p>An E-Mail has been sent to. Please confirm by clicking on the link in that E-Mail!</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,33 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-box">
|
||||
{% if form.errors %}
|
||||
<p>{{ form.errors }}</p>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="{% url 'django_registration_register' %}">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
<tr>
|
||||
<td>{{ form.username.label_tag }}</td>
|
||||
<td>{{ form.username }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ form.email.label_tag }}</td>
|
||||
<td>{{ form.email }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ form.password1.label_tag }}</td>
|
||||
<td>{{ form.password1 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ form.password2.label_tag }}</td>
|
||||
<td>{{ form.password2 }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<input type="submit" value="Register" />
|
||||
<input type="hidden" name="next" value="{{ next }}" />
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,38 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-box">
|
||||
{% if form.errors %}
|
||||
<p>Your username and password didn't match. Please try again.</p>
|
||||
{% endif %}
|
||||
|
||||
{% if next %}
|
||||
{% if user.is_authenticated %}
|
||||
<p>Your account doesn't have access to this page. To proceed,
|
||||
please login with an account that has access.</p>
|
||||
{% else %}
|
||||
<p>Please login to see this page.</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="{% url 'login' %}">
|
||||
{% csrf_token %}
|
||||
<table>
|
||||
<tr>
|
||||
<td>{{ form.username.label_tag }}</td>
|
||||
<td>{{ form.username }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ form.password.label_tag }}</td>
|
||||
<td>{{ form.password }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<input type="submit" value="login" />
|
||||
<input type="hidden" name="next" value="{{ next }}" />
|
||||
</form>
|
||||
|
||||
{# Assumes you setup the password_reset view in your URLconf #}
|
||||
<p><a href="{% url 'password_reset' %}">Lost password?</a></p>
|
||||
<p><a href="{% url 'django_registration_register' %}">Create a free account</a></p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,9 @@
|
||||
from django.contrib.auth import authenticate
|
||||
from django.shortcuts import render, redirect
|
||||
|
||||
def home(request):
|
||||
# if not logged in => redirect to login screen
|
||||
if not request.user.is_authenticated:
|
||||
return redirect('/accounts/login/')
|
||||
# if logged in => redirect to monitor view
|
||||
return redirect('/monitor')
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MonitorConfig(AppConfig):
|
||||
name = 'monitor'
|
||||
@@ -0,0 +1,90 @@
|
||||
from django.db import connection
|
||||
from apps.transactions.models import Transaction
|
||||
from apps.rates.models import ExchangeRate
|
||||
from decimal import Decimal
|
||||
import datetime
|
||||
|
||||
class Calc:
|
||||
def ShowDiffRate(self, DayDiff, CurrentRate, Crypto, Fiat):
|
||||
with connection.cursor() as cursor:
|
||||
sql = """SELECT rate, datetime_valid FROM exchangerate WHERE crypto_currency = %s AND fiat_currency = %s
|
||||
AND datetime_valid BETWEEN %s AND %s
|
||||
ORDER BY datetime_valid DESC"""
|
||||
startDate = datetime.datetime.now() - datetime.timedelta(days=int(DayDiff))
|
||||
endDate = startDate + datetime.timedelta(days=1)
|
||||
cursor.execute(sql, [Crypto, Fiat, startDate, endDate])
|
||||
rateMinusXDay = cursor.fetchone()
|
||||
if rateMinusXDay:
|
||||
return {"dateRelative": "%s days ago" % (DayDiff,), "date" : rateMinusXDay[1], "rateEUR": rateMinusXDay[0],
|
||||
"diffPercentage": (CurrentRate.rate-Decimal(rateMinusXDay[0]))/Decimal(rateMinusXDay[0])*100, "rateUSD": None}
|
||||
return None
|
||||
|
||||
def GetCurrentValue(self, userid, crypto, total_investment, current_value, total_tax_free):
|
||||
amount_kept = 0
|
||||
out = {}
|
||||
out["crypto"] = crypto
|
||||
|
||||
with connection.cursor() as cursor:
|
||||
sql = """SELECT SUM(amount_after_fee) as after_fee, SUM(amount) as amount FROM `transaction` WHERE amount >= 0 and crypto_currency=%s and owner_id=%s"""
|
||||
cursor.execute(sql, [crypto, userid])
|
||||
bought = cursor.fetchone()
|
||||
if bought[1]:
|
||||
out["bought"] = bought[1]
|
||||
total_investment += Decimal(bought[1])
|
||||
amount_kept += Decimal(bought[0])
|
||||
else:
|
||||
out["bought"] = None
|
||||
|
||||
with connection.cursor() as cursor:
|
||||
sql = """SELECT SUM(amount_before_fee) as before_fee, SUM(amount) as amount FROM `transaction` WHERE amount < 0 and crypto_currency=%s and owner_id=%s"""
|
||||
cursor.execute(sql, [crypto, userid])
|
||||
sold = cursor.fetchone()
|
||||
if sold[1]:
|
||||
out["sold"] = sold[1]
|
||||
total_investment += Decimal(sold[1])
|
||||
amount_kept += Decimal(sold[0])
|
||||
else:
|
||||
out["sold"] = None
|
||||
|
||||
rateEUR = ExchangeRate.objects.filter(crypto_currency=crypto, fiat_currency='EUR').order_by('-datetime_valid').first()
|
||||
rateUSD = ExchangeRate.objects.filter(crypto_currency=crypto, fiat_currency='USD').order_by('-datetime_valid').first()
|
||||
|
||||
if rateEUR:
|
||||
cv = Decimal(rateEUR.rate) * amount_kept
|
||||
current_value += cv
|
||||
out["current_value"] = cv
|
||||
out["amount_kept"] = amount_kept
|
||||
out["rateEUR"] = rateEUR.rate
|
||||
else:
|
||||
out["current_value"] = None
|
||||
out["amount_kept"] = None
|
||||
out["rateEUR"] = None
|
||||
|
||||
out["rates"] = []
|
||||
if rateUSD and rateEUR:
|
||||
out["rates"].append({"dateRelative": "Now", "date" : rateEUR.datetime_valid, "rateEUR": rateEUR.rate, "diffPercentage": None, "rateUSD": rateUSD.rate})
|
||||
|
||||
if rateEUR:
|
||||
for daydiff in ["1", "3", "7", "14", "30"]:
|
||||
diffrate = self.ShowDiffRate(daydiff, rateEUR, crypto, 'EUR')
|
||||
if diffrate:
|
||||
out["rates"].append(diffrate)
|
||||
|
||||
amount_within_past_year = 0
|
||||
with connection.cursor() as cursor:
|
||||
sql = """SELECT SUM(amount_after_fee) as amount FROM `transaction` WHERE amount > 0 and crypto_currency=%s and owner_id=%s and date_valid>%s"""
|
||||
cursor.execute(sql, [crypto, userid, datetime.datetime.now() - datetime.timedelta(days=365)])
|
||||
bought = cursor.fetchone()
|
||||
out["bought_recently"] = None
|
||||
if bought[0]:
|
||||
out["bought_recently"] = bought[0]
|
||||
amount_within_past_year = Decimal(bought[0])
|
||||
amount_available_to_sell = amount_kept - amount_within_past_year
|
||||
out["bought_tax_free"] = None
|
||||
out["value_tax_free"] = None
|
||||
if rateEUR:
|
||||
out["bought_tax_free"] = amount_available_to_sell
|
||||
out["value_tax_free"] = amount_available_to_sell * rateEUR.rate
|
||||
total_tax_free += out["value_tax_free"]
|
||||
|
||||
return (total_investment, current_value, total_tax_free, rateEUR.rate, rateUSD.rate, out)
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
@@ -0,0 +1,64 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-box">
|
||||
<h2>Monitor</h2>
|
||||
<p>Hint: these numbers are not very accurate.</p>
|
||||
|
||||
{% for c in cryptos %}
|
||||
<input type="checkbox" id="acc{{ c.crypto }}" />
|
||||
<label for="acc{{ c.crypto }}">
|
||||
{{ c.crypto }}
|
||||
{% if c.rateEUR %}{{c.rateEUR|floatformat:0}} EUR{% endif %}
|
||||
{% if c.rateUSD %}{{c.rateUSD|floatformat:0}} USD{% endif %}
|
||||
</label>
|
||||
|
||||
<div class="content">
|
||||
{% if c.bought %}
|
||||
We have bought {{ c.crypto }} for {{ c.bought|floatformat:2 }} EUR<br/>
|
||||
{% endif %}
|
||||
{% if c.sold %}
|
||||
We have sold {{ c.crypto }} for {{ c.sold|floatformat:2 }} EUR<br/>
|
||||
{% endif %}
|
||||
{% if c.amount_kept %}
|
||||
Current value of our {{ c.amount_kept|floatformat:3 }} {{ c.crypto }} is {{ c.current_value|floatformat:2 }} EUR<br/>
|
||||
{% endif %}
|
||||
{% if c.bought_recently %}
|
||||
We have bought within the last 12 months: {{ c.bought_recently|floatformat:3 }} {{ c.crypto }}<br/>
|
||||
{% endif %}
|
||||
{% if c.bought_tax_free %}
|
||||
We can sell without paying taxes: {{ c.bought_tax_free|floatformat:3 }} {{ c.crypto }} for {{ c.value_tax_free|floatformat:2 }} EUR<br/>
|
||||
{% endif %}
|
||||
|
||||
{% if c.rates %}
|
||||
<table>
|
||||
{% for r in c.rates %}
|
||||
<tr>
|
||||
<td>{{ r.dateRelative }}</td>
|
||||
<td>{{ r.date|date:'Y-m-d' }}</td>
|
||||
<td>{{ r.rateEUR|floatformat:0 }} EUR/{{ c.crypto }}
|
||||
{% if r.rateUSD %}
|
||||
<br/>
|
||||
{{ r.rateUSD|floatformat:0 }} USD/{{ c.crypto }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{% if r.diffPercentage %}
|
||||
{{ r.diffPercentage|floatformat:1 }}%
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
<br/><a href="/transactions/show?crypto={{ c.crypto }}">My transactions</a><br/>
|
||||
<br/>
|
||||
Google: <br/>
|
||||
<a href='https://www.google.com/search?channel=crow2&client=firefox-b-d&q={{ c.crypto }}+in+eur%3D' target='_blank'>{{ c.crypto }} in EUR</a><br/>
|
||||
<a href='https://www.google.com/search?channel=crow2&client=firefox-b-d&q={{ c.crypto }}+in+usd%3D' target='_blank'>{{ c.crypto }} in USD</a><br/>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,22 @@
|
||||
from django.shortcuts import render, redirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from apps.transactions.models import Transaction
|
||||
from apps.rates.models import ExchangeRate
|
||||
from apps.monitor.calc import Calc
|
||||
|
||||
@login_required
|
||||
def monitor(request):
|
||||
transactions = Transaction.objects.filter(owner=request.user)
|
||||
crypto_currencies = {tr.crypto_currency for tr in transactions}
|
||||
cryptos = []
|
||||
total_investment = 0
|
||||
current_value = 0
|
||||
total_tax_free = 0
|
||||
calc = Calc()
|
||||
|
||||
for crypto in crypto_currencies:
|
||||
(total_investment, current_value, total_tax_free, rateEUR, rateUSD, out2) = calc.GetCurrentValue(request.user.id, crypto, total_investment, current_value, total_tax_free)
|
||||
|
||||
cryptos.append({"crypto": crypto, "rateEUR": rateEUR, "rateUSD": rateUSD, **out2})
|
||||
|
||||
return render(request,"monitor.html",{'cryptos':cryptos})
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class RatesConfig(AppConfig):
|
||||
name = 'rates'
|
||||
@@ -0,0 +1,27 @@
|
||||
# Generated by Django 3.1.4 on 2021-01-03 21:17
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ExchangeRate',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('crypto_currency', models.CharField(max_length=10)),
|
||||
('fiat_currency', models.CharField(max_length=10)),
|
||||
('rate', models.DecimalField(decimal_places=10, max_digits=24)),
|
||||
('datetime_valid', models.DateTimeField(verbose_name='datetime valid')),
|
||||
],
|
||||
options={
|
||||
'db_table': 'exchangerate',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
class ExchangeRate(models.Model):
|
||||
crypto_currency = models.CharField(max_length=10)
|
||||
fiat_currency = models.CharField(max_length=10)
|
||||
rate = models.DecimalField(max_digits=24, decimal_places=10)
|
||||
datetime_valid = models.DateTimeField('datetime valid')
|
||||
class Meta:
|
||||
db_table = "exchangerate"
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class TransactionsConfig(AppConfig):
|
||||
name = 'transactions'
|
||||
@@ -0,0 +1,14 @@
|
||||
from django import forms
|
||||
from apps.transactions.models import Transaction
|
||||
#from datetimepicker.widgets import DateTimePicker
|
||||
#from django.contrib.admin.widgets import AdminDateWidget
|
||||
|
||||
class TransactionForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Transaction
|
||||
fields = "__all__"
|
||||
|
||||
# https://stackoverflow.com/a/52702275/1632368
|
||||
#date_valid = forms.DateField(widget=AdminDateWidget())
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# Generated by Django 3.1.4 on 2020-12-26 10:16
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Transaction',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('crypto_currency', models.CharField(max_length=10)),
|
||||
('amount_before_fee', models.DecimalField(decimal_places=10, max_digits=24)),
|
||||
('amount_after_fee', models.DecimalField(decimal_places=10, max_digits=24)),
|
||||
('exchange_rate', models.DecimalField(decimal_places=10, max_digits=24)),
|
||||
('fiat_currency', models.CharField(max_length=10)),
|
||||
('amount', models.DecimalField(decimal_places=10, max_digits=24)),
|
||||
('date_valid', models.DateTimeField(verbose_name='date transfered')),
|
||||
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'db_table': 'transaction',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,15 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
# Create your models here.
|
||||
class Transaction(models.Model):
|
||||
crypto_currency = models.CharField(max_length=10)
|
||||
owner = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
amount_before_fee = models.DecimalField(max_digits=24, decimal_places=10)
|
||||
amount_after_fee = models.DecimalField(max_digits=24, decimal_places=10)
|
||||
exchange_rate = models.DecimalField(max_digits=24, decimal_places=10)
|
||||
fiat_currency = models.CharField(max_length=10)
|
||||
amount = models.DecimalField(max_digits=24, decimal_places=10)
|
||||
date_valid = models.DateTimeField('date transfered')
|
||||
class Meta:
|
||||
db_table = "transaction"
|
||||
@@ -0,0 +1,90 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-box">
|
||||
<form method="POST" class="post-form" action="/transactions/add">
|
||||
{% csrf_token %}
|
||||
<div class="container">
|
||||
<br>
|
||||
{% if form.errors %}
|
||||
{% for field in form %}
|
||||
{% for error in field.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<strong>{{field.name}}: {{ error|escape }}</strong>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% for error in form.non_field_errors %}
|
||||
<div class="alert alert-danger">
|
||||
<strong>{{ error|escape }}</strong>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-1 col-form-label"></label>
|
||||
<div class="col-sm-4">
|
||||
<h3>Add transaction</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Crypto Currency:</label>
|
||||
<div class="col-sm-4">
|
||||
{{ form.crypto_currency }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Amount before fee:</label>
|
||||
<div class="col-sm-4">
|
||||
{{ form.amount_before_fee }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Amount after fee:</label>
|
||||
<div class="col-sm-4">
|
||||
{{ form.amount_after_fee }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Exchange Rate:</label>
|
||||
<div class="col-sm-4">
|
||||
{{ form.exchange_rate }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Fiat Currency:</label>
|
||||
<div class="col-sm-4">
|
||||
{{ form.fiat_currency }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Fiat Amount:</label>
|
||||
<div class="col-sm-4">
|
||||
{{ form.amount }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Date valid:</label>
|
||||
<div class="col-sm-4">
|
||||
{{ form.date_valid }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-1 col-form-label"></label>
|
||||
<div class="col-sm-4">
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,90 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-box">
|
||||
<form method="POST" class="post-form" action="/transactions/update/{{transaction.id}}">
|
||||
{% csrf_token %}
|
||||
<div class="container">
|
||||
<br>
|
||||
{% if form.errors %}
|
||||
{% for field in form %}
|
||||
{% for error in field.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<strong>{{field.name}}: {{ error|escape }}</strong>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% for error in form.non_field_errors %}
|
||||
<div class="alert alert-danger">
|
||||
<strong>{{ error|escape }}</strong>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-1 col-form-label"></label>
|
||||
<div class="col-sm-4">
|
||||
<h3>Update Transaction</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Crypto Currency:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" name="crypto_currency" id="id_crypto_currency" required maxlength="10" value="{{ transaction.crypto_currency }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Amount before fee:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="decimal" name="amount_before_fee" id="id_amount_before_fee" required value="{{ transaction.amount_before_fee }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Amount after fee:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="decimal" name="amount_after_fee" id="id_amount_after_fee" required value="{{ transaction.amount_after_fee }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Exchange Rate:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="decimal" name="exchange_rate" id="id_exchange_rate" required value="{{ transaction.exchange_rate }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Fiat Currency:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" name="fiat_currency" id="id_fiat_currency" required maxlength="10" value="{{ transaction.fiat_currency }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Fiat Amount:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="decimal" name="amount" id="id_amount" required value="{{ transaction.amount }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label">Date valid:</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" name="date_valid" id="id_date_valid" required value="{{ transaction.date_valid|date:'Y-m-d H:i:s' }}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-1 col-form-label"></label>
|
||||
<div class="col-sm-4">
|
||||
<button type="submit" class="btn btn-success">Update</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,41 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load humanize %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-box">
|
||||
<center><a href="/transactions/add" class="button button-primary">Add New Record</a></center>
|
||||
<br/>
|
||||
<table class="table table-striped table-bordered table-sm">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Amount</th>
|
||||
<th>Value</th>
|
||||
<th colspan="2">Rate</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for transaction in transactions %}
|
||||
<tr>
|
||||
<td>{{ transaction.date_valid }}</td>
|
||||
<td>{{ transaction.amount_before_fee|floatformat:3 }} {{ transaction.crypto_currency }}</td>
|
||||
<td>{{ transaction.amount|floatformat:2 }} {{ transaction.fiat_currency }}</td>
|
||||
<td>{% if transaction.amount < 0 %}
|
||||
{{ transaction.exchange_rate|floatformat:0 }} {{ transaction.crypto_currency }}/{{ transaction.fiat_currency }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{% if transaction.amount > 0 %}
|
||||
{{ transaction.exchange_rate|floatformat:0 }} {{ transaction.crypto_currency }}/{{ transaction.fiat_currency }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<a href="/transactions/edit/{{ transaction.id }}"><span class="glyphicon glyphicon-pencil" >Edit</span></a>
|
||||
<a href="/transactions/delete/{{ transaction.id }}" onclick="return confirm('Are you sure?')">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -0,0 +1,52 @@
|
||||
from django.shortcuts import render, redirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from apps.transactions.forms import TransactionForm
|
||||
from apps.transactions.models import Transaction
|
||||
|
||||
@login_required
|
||||
def add(request):
|
||||
if request.method == "POST":
|
||||
# request.POST is immutable, so make a copy
|
||||
values = request.POST.copy()
|
||||
values['owner'] = request.user.id
|
||||
form = TransactionForm(values)
|
||||
if form.is_valid():
|
||||
try:
|
||||
form.save()
|
||||
return redirect('/transactions/show')
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
form = TransactionForm()
|
||||
return render(request,'add.html',{'form':form})
|
||||
|
||||
@login_required
|
||||
def show(request):
|
||||
if 'crypto' in request.GET:
|
||||
transactions = Transaction.objects.filter(owner=request.user, crypto_currency=request.GET['crypto']).order_by('-date_valid')
|
||||
else:
|
||||
transactions = Transaction.objects.filter(owner=request.user).order_by('-date_valid')
|
||||
return render(request,"show.html",{'transactions':transactions})
|
||||
|
||||
@login_required
|
||||
def edit(request, id):
|
||||
transaction = Transaction.objects.get(id=id, owner=request.user)
|
||||
return render(request,'edit.html', {'transaction':transaction})
|
||||
|
||||
@login_required
|
||||
def update(request, id):
|
||||
transaction = Transaction.objects.get(id=id, owner=request.user)
|
||||
# request.POST is immutable, so make a copy
|
||||
values = request.POST.copy()
|
||||
values['owner'] = request.user.id
|
||||
form = TransactionForm(values, instance = transaction)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return redirect("/transactions/show")
|
||||
return render(request, 'edit.html', {'transaction': transaction, 'form': form})
|
||||
|
||||
@login_required
|
||||
def destroy(request, id):
|
||||
transaction = Transaction.objects.get(id=id, owner=request.user.id)
|
||||
transaction.delete()
|
||||
return redirect("/transactions/show")
|
||||
Reference in New Issue
Block a user