initial commit

This commit is contained in:
2021-01-07 22:12:05 +01:00
commit e385650802
51 changed files with 1048 additions and 0 deletions
+23
View File
@@ -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 %}
+9
View File
@@ -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')
View File
+3
View File
@@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.
+5
View File
@@ -0,0 +1,5 @@
from django.apps import AppConfig
class MonitorConfig(AppConfig):
name = 'monitor'
+90
View File
@@ -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)
View File
+3
View File
@@ -0,0 +1,3 @@
from django.db import models
# Create your models here.
+64
View File
@@ -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 %}
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+22
View File
@@ -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})
View File
+3
View File
@@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.
+5
View File
@@ -0,0 +1,5 @@
from django.apps import AppConfig
class RatesConfig(AppConfig):
name = 'rates'
+27
View File
@@ -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',
},
),
]
View File
+10
View File
@@ -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"
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+3
View File
@@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.
View File
+3
View File
@@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.
+5
View File
@@ -0,0 +1,5 @@
from django.apps import AppConfig
class TransactionsConfig(AppConfig):
name = 'transactions'
+14
View File
@@ -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',
},
),
]
+15
View File
@@ -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"
+90
View File
@@ -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 %}
+90
View File
@@ -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 %}
+41
View File
@@ -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 %}
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+52
View File
@@ -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")