mirror of
https://github.com/peter-tanner/money-manager.git
synced 2024-11-30 06:10:17 +08:00
logs system
This commit is contained in:
parent
07c0f40b05
commit
33eb31f86e
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,12 +1,13 @@
|
|||
# nah i don't think i want you to have my receipts thanks...
|
||||
receipts/
|
||||
receipts/*
|
||||
db_backup/
|
||||
|
||||
|
||||
etc/
|
||||
test.py
|
||||
localhost_config.py
|
||||
static/
|
||||
/static/
|
||||
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
|
|
|
@ -10,6 +10,7 @@ For the full list of settings and their values, see
|
|||
https://docs.djangoproject.com/en/4.2/ref/settings/
|
||||
"""
|
||||
|
||||
import os
|
||||
from import_export.formats.base_formats import CSV, XLSX
|
||||
from pathlib import Path
|
||||
|
||||
|
@ -135,3 +136,5 @@ STATIC_URL = "static/"
|
|||
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
|
||||
|
|
|
@ -5,7 +5,7 @@ from django.contrib import admin
|
|||
from util import next_payday, rgb_tuple_to_hex
|
||||
|
||||
from .admin_base import AdminBase, DeletedListFilter, DeletableAdminForm
|
||||
from .models import Expense, ExpenseCategory, Timesheet, TimesheetRate, Vendor
|
||||
from .models import Log, Expense, ExpenseCategory, Timesheet, TimesheetRate, Vendor
|
||||
from django import forms
|
||||
from django.utils import timezone
|
||||
from import_export import resources
|
||||
|
@ -13,6 +13,38 @@ from import_export.admin import ImportExportModelAdmin
|
|||
from admincharts.admin import AdminChartMixin
|
||||
from admincharts.utils import months_between_dates
|
||||
from djmoney.contrib.exchange.models import convert_money
|
||||
from django.utils.html import format_html
|
||||
|
||||
|
||||
class LogsAdminForm(DeletableAdminForm):
|
||||
class Meta:
|
||||
model = Log
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
@admin.register(Log)
|
||||
class LogsAdmin(AdminBase):
|
||||
class Media:
|
||||
css = {"all": ("/static/logs.css",)}
|
||||
|
||||
def truncated_title(self, instance):
|
||||
return f"{instance.title[:2]}...{instance.title[-1:]}"
|
||||
|
||||
list_display = (
|
||||
"title",
|
||||
"truncated_title",
|
||||
"date",
|
||||
"goodness_value",
|
||||
)
|
||||
list_display_links = (
|
||||
"title",
|
||||
"truncated_title",
|
||||
)
|
||||
search_fields = (
|
||||
"title",
|
||||
"date",
|
||||
)
|
||||
form = LogsAdminForm
|
||||
|
||||
|
||||
class VendorAdminForm(DeletableAdminForm):
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 4.2.5 on 2023-10-04 10:32
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('expenses', '0004_vendor_remove_expense_merchant_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='expense',
|
||||
name='cash',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='historicalexpense',
|
||||
name='cash',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
52
expenses/migrations/0006_logs_historicallogs.py
Normal file
52
expenses/migrations/0006_logs_historicallogs.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
# Generated by Django 4.2.5 on 2023-10-06 13:43
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import simple_history.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('expenses', '0005_expense_cash_historicalexpense_cash'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Logs',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('deleted', models.BooleanField(default=False)),
|
||||
('title', models.TextField(blank=True)),
|
||||
('date', models.DateTimeField(blank=True, null=True)),
|
||||
('information', models.TextField(blank=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='HistoricalLogs',
|
||||
fields=[
|
||||
('id', models.BigIntegerField(auto_created=True, blank=True, db_index=True, verbose_name='ID')),
|
||||
('deleted', models.BooleanField(default=False)),
|
||||
('title', models.TextField(blank=True)),
|
||||
('date', models.DateTimeField(blank=True, null=True)),
|
||||
('information', models.TextField(blank=True)),
|
||||
('history_id', models.AutoField(primary_key=True, serialize=False)),
|
||||
('history_date', models.DateTimeField(db_index=True)),
|
||||
('history_change_reason', models.CharField(max_length=100, null=True)),
|
||||
('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)),
|
||||
('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'historical logs',
|
||||
'verbose_name_plural': 'historical logss',
|
||||
'ordering': ('-history_date', '-history_id'),
|
||||
'get_latest_by': ('history_date', 'history_id'),
|
||||
},
|
||||
bases=(simple_history.models.HistoricalChanges, models.Model),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 4.2.5 on 2023-10-06 13:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('expenses', '0006_logs_historicallogs'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='historicallogs',
|
||||
name='title',
|
||||
field=models.CharField(blank=True, max_length=256),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='logs',
|
||||
name='title',
|
||||
field=models.CharField(blank=True, max_length=256),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 4.2.5 on 2023-10-06 13:49
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('expenses', '0007_alter_historicallogs_title_alter_logs_title'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameModel(
|
||||
old_name='HistoricalLogs',
|
||||
new_name='HistoricalLog',
|
||||
),
|
||||
migrations.RenameModel(
|
||||
old_name='Logs',
|
||||
new_name='Log',
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='historicallog',
|
||||
options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical log', 'verbose_name_plural': 'historical logs'},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 4.2.5 on 2023-10-08 09:55
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('expenses', '0008_rename_historicallogs_historicallog_rename_logs_log_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='historicallog',
|
||||
name='goodness_value',
|
||||
field=models.FloatField(default=0.0, validators=[django.core.validators.MinValueValidator(-10.0), django.core.validators.MaxValueValidator(10.0)]),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='log',
|
||||
name='goodness_value',
|
||||
field=models.FloatField(default=0.0, validators=[django.core.validators.MinValueValidator(-10.0), django.core.validators.MaxValueValidator(10.0)]),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='log',
|
||||
constraint=models.CheckConstraint(check=models.Q(('goodness_value__gte', -10.0), ('goodness_value__lte', 10.0)), name='log_goodness_value_range'),
|
||||
),
|
||||
]
|
|
@ -4,7 +4,8 @@ from django.utils import timezone
|
|||
from djmoney.models.fields import MoneyField, Money
|
||||
from .deletable_model import DeletableModel
|
||||
from util import truncate_string # new line
|
||||
from django.db.models import Q
|
||||
from django.db.models import Q, CheckConstraint
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
|
||||
# class ExpenseManager(models.Manager):
|
||||
# def active(self):
|
||||
|
@ -30,6 +31,32 @@ from django.db.models import Q
|
|||
# actions = [soft_delete_selected]
|
||||
|
||||
|
||||
class Log(DeletableModel):
|
||||
# TODO: Use Markdown formatting!
|
||||
title = models.CharField(max_length=256, blank=True)
|
||||
date = models.DateTimeField(null=True, blank=True)
|
||||
goodness_value = models.FloatField(
|
||||
default=0.0,
|
||||
validators=(
|
||||
MinValueValidator(-10.0),
|
||||
MaxValueValidator(10.0),
|
||||
),
|
||||
)
|
||||
information = models.TextField(blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.date}: {self.title}"
|
||||
|
||||
class Meta:
|
||||
constraints = (
|
||||
# for checking in the DB
|
||||
CheckConstraint(
|
||||
check=Q(goodness_value__gte=-10.0) & Q(goodness_value__lte=10.0),
|
||||
name="log_goodness_value_range",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class TimesheetRate(DeletableModel):
|
||||
rate = MoneyField(
|
||||
decimal_places=3,
|
||||
|
@ -141,6 +168,7 @@ class Expense(DeletableModel):
|
|||
blank=True,
|
||||
related_name="expenses",
|
||||
)
|
||||
cash = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.date} {self.price} {truncate_string(self.description,32)}"
|
||||
|
|
12
expenses/static/logs.css
Normal file
12
expenses/static/logs.css
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* Hide title of log when mouse is not hovering over it for privacy */
|
||||
.field-title:not(:hover) > a {
|
||||
color: transparent;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.field-goodness_value:not(:hover) {
|
||||
color: transparent;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
Loading…
Reference in New Issue
Block a user