Add currency management
Fix color picker Add exchange rate updater submodule Fix logging in celery A few invoicing fixes HTTP request class Navigation/URL updates
This commit is contained in:
parent
2e8bbdd8a7
commit
31b0eed298
29 changed files with 397 additions and 50 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,3 +3,4 @@ expephalon/custom_settings.py
|
|||
__pycache__/
|
||||
migrations/
|
||||
*.pid
|
||||
.vscode/
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -16,3 +16,6 @@
|
|||
[submodule "totp"]
|
||||
path = totp
|
||||
url = git@kumig.it:kumisystems/expephalon-totp.git
|
||||
[submodule "ratesapi"]
|
||||
path = ratesapi
|
||||
url = git@kumig.it:kumisystems/expephalon-ratesapi.git
|
||||
|
|
13
core/classes/http.py
Normal file
13
core/classes/http.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
from urllib.request import Request, urlopen
|
||||
|
||||
from core.helpers.expephalon import version_string
|
||||
|
||||
class HTTP:
|
||||
def __init__(self, url, no_user_agent=False, *args, **kwargs):
|
||||
self.request = Request(url, *args, **kwargs)
|
||||
if not no_user_agent:
|
||||
self.request.add_header("User-Agent", f"Expephalon/{version_string} (https://kumi.systems/)")
|
||||
self.fetch()
|
||||
|
||||
def fetch(self):
|
||||
self.data = urlopen(self.request).read()
|
|
@ -19,7 +19,7 @@ class NavItem:
|
|||
return self.__path if (self.__path.startswith("/") or "://" in self.__path) else reverse(self.__path)
|
||||
|
||||
class NavSection:
|
||||
def __init__(self, name: str, icon: str):
|
||||
def __init__(self, name: str, icon: str = ""):
|
||||
self.__items = []
|
||||
self.__name = name
|
||||
self.__icon = icon
|
||||
|
|
10
core/helpers/expephalon.py
Normal file
10
core/helpers/expephalon.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from django.conf import settings
|
||||
|
||||
from git import Repo
|
||||
|
||||
def version_string():
|
||||
repo = Repo(settings["BASE_DIR"])
|
||||
try:
|
||||
return repo.head.commit.hexsha
|
||||
except:
|
||||
return "unknown"
|
|
@ -5,7 +5,7 @@ from django.conf import settings
|
|||
|
||||
# Dashboard Section
|
||||
|
||||
dashboard_section = NavSection("Dashboard", "")
|
||||
dashboard_section = NavSection("Dashboard")
|
||||
|
||||
dashboard_item = NavItem("Dashboard", "fa-rocket", "dashboard")
|
||||
|
||||
|
@ -15,7 +15,7 @@ navigations["backend_main"].add_section(dashboard_section)
|
|||
|
||||
# Clients Section
|
||||
|
||||
clients_section = NavSection("Clients", "")
|
||||
clients_section = NavSection("Clients")
|
||||
|
||||
client_list_item = NavItem("List Clients", "fa-user-tag", "clients")
|
||||
client_add_item = NavItem("Add Client", "fa-user-edit", "clients_create")
|
||||
|
@ -31,7 +31,7 @@ navigations["backend_main"].add_section(clients_section)
|
|||
|
||||
# Quotes Section
|
||||
|
||||
quotes_section = NavSection("Quotes", "")
|
||||
quotes_section = NavSection("Quotes")
|
||||
|
||||
quote_list_item = NavItem("List Quotes", "fa-file-invoice-dollar", "backendni")
|
||||
quote_create_item = NavItem("Create Quote", "fa-plus-square", "backendni")
|
||||
|
@ -43,7 +43,7 @@ navigations["backend_main"].add_section(quotes_section)
|
|||
|
||||
# Billing Section
|
||||
|
||||
billing_section = NavSection("Billing", "")
|
||||
billing_section = NavSection("Billing")
|
||||
|
||||
invoice_list_item = NavItem("List Invoices", "fa-file-invoice-dollar", "invoices")
|
||||
invoice_create_item = NavItem("Create Invoice", "fa-plus-square", "invoices_create")
|
||||
|
@ -61,7 +61,7 @@ navigations["backend_main"].add_section(billing_section)
|
|||
|
||||
# Support Section
|
||||
|
||||
support_section = NavSection("Support", "")
|
||||
support_section = NavSection("Support")
|
||||
|
||||
ticket_view_item = NavItem("View Tickets", "fa-life-ring", "backendni")
|
||||
ticket_add_item = NavItem("Add Ticket", "fa-plus-square", "backendni")
|
||||
|
@ -75,19 +75,32 @@ navigations["backend_main"].add_section(support_section)
|
|||
|
||||
# Reports Section
|
||||
|
||||
reports_section = NavSection("Reports", "")
|
||||
reports_section = NavSection("Reports")
|
||||
|
||||
report_period_item = NavItem("Income by period", "fa-chart-bar", "backendni")
|
||||
report_forecast_item = NavItem("Income Forecast", "fa-chart-area", "backendni")
|
||||
report_more_item = NavItem("More reports...", "fa-chalkboard", "backendni")
|
||||
|
||||
reports_section.add_item(report_period_item)
|
||||
reports_section.add_item(report_forecast_item)
|
||||
|
||||
navigations["backend_main"].add_section(reports_section)
|
||||
|
||||
# Products Section
|
||||
|
||||
products_section = NavSection("Products")
|
||||
|
||||
product_administration_item = NavItem("Products", "fa-cube", "backendni")
|
||||
pgroup_administration_item = NavItem("Product Groups", "fa-cubes", "backendni")
|
||||
|
||||
products_section.add_item(product_administration_item)
|
||||
products_section.add_item(pgroup_administration_item)
|
||||
|
||||
navigations["backend_main"].add_section(products_section)
|
||||
|
||||
# Administration Section
|
||||
|
||||
administration_section = NavSection("Administration", "")
|
||||
administration_section = NavSection("Administration")
|
||||
|
||||
user_administration_item = NavItem("Administrator Users", "fa-users-cog", "admins")
|
||||
brand_administration_item = NavItem("Brands", "fa-code-branch", "brands")
|
||||
|
@ -95,9 +108,9 @@ ratelimit_administration_item = NavItem("Firewall", "fa-shield-alt", "ratelimits
|
|||
sms_administration_item = NavItem("SMS Gateway", "fa-sms", "backendni")
|
||||
otp_administration_item = NavItem("Two-Factor Authentication", "fa-id-badge", "backendni")
|
||||
backup_administration_item = NavItem("Backups", "fa-shield-alt", "backendni")
|
||||
product_administration_item = NavItem("Products", "fa-cube", "backendni")
|
||||
pgroup_administration_item = NavItem("Product Groups", "fa-cubes", "backendni")
|
||||
payment_administration_item = NavItem("Payment Gateways", "fa-credit-card", "backendni")
|
||||
currency_administration_item = NavItem("Currencies", "fa-coins", "currencies")
|
||||
tax_administration_item = NavItem("Tax Settings", "fa-handshake", "backendni")
|
||||
dbsettings_item = NavItem("Database Settings", "fa-database", "dbsettings")
|
||||
|
||||
administration_section.add_item(user_administration_item)
|
||||
|
@ -106,11 +119,9 @@ administration_section.add_item(ratelimit_administration_item)
|
|||
administration_section.add_item(sms_administration_item)
|
||||
administration_section.add_item(otp_administration_item)
|
||||
administration_section.add_item(backup_administration_item)
|
||||
administration_section.add_item(product_administration_item)
|
||||
administration_section.add_item(pgroup_administration_item)
|
||||
administration_section.add_item(payment_administration_item)
|
||||
|
||||
if "dbsettings" in settings.INSTALLED_APPS:
|
||||
administration_section.add_item(dbsettings_item)
|
||||
administration_section.add_item(currency_administration_item)
|
||||
administration_section.add_item(tax_administration_item)
|
||||
administration_section.add_item(dbsettings_item)
|
||||
|
||||
navigations["backend_main"].add_section(administration_section)
|
|
@ -8,8 +8,9 @@ from core.urls.backend.brands import urlpatterns as brandpatterns
|
|||
from core.urls.backend.firewall import urlpatterns as firewallpatterns
|
||||
from core.urls.backend.invoices import urlpatterns as invoicepatterns
|
||||
from core.urls.backend.clientgroups import urlpatterns as clientgrouppatterns
|
||||
from core.urls.backend.currencies import urlpatterns as currencypatterns
|
||||
|
||||
urlpatterns = adminpatterns + clientpatterns + dbsettingspatterns + brandpatterns + firewallpatterns + invoicepatterns + clientgrouppatterns
|
||||
urlpatterns = adminpatterns + clientpatterns + dbsettingspatterns + brandpatterns + firewallpatterns + invoicepatterns + clientgrouppatterns + currencypatterns
|
||||
|
||||
urlpatterns.append(path('admin/', DashboardView.as_view(), name="dashboard"))
|
||||
urlpatterns.append(path('admin/oops/', BackendNotImplementedView.as_view(), name="backendni"))
|
10
core/urls/backend/currencies.py
Normal file
10
core/urls/backend/currencies.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
from django.urls import path
|
||||
|
||||
from core.views.backend.currencies import CurrencyCreateView, CurrencyDeleteView, CurrencyEditView, CurrencyListView
|
||||
|
||||
urlpatterns = []
|
||||
|
||||
urlpatterns.append(path('admin/currencies/', CurrencyListView.as_view(), name="currencies"))
|
||||
urlpatterns.append(path("admin/currencies/<pk>/delete/", CurrencyDeleteView.as_view(), name="currencies_delete"))
|
||||
urlpatterns.append(path("admin/currencies/<pk>/edit/", CurrencyEditView.as_view(), name="currencies_edit"))
|
||||
urlpatterns.append(path("admin/currencies/create/", CurrencyCreateView.as_view(), name="currencies_create"))
|
46
core/views/backend/currencies.py
Normal file
46
core/views/backend/currencies.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
from django.conf import settings
|
||||
from django.urls import reverse_lazy
|
||||
|
||||
from core.models.local import Currency
|
||||
from core.views.generic import BackendListView, BackendUpdateView, BackendDeleteView, BackendCreateView
|
||||
|
||||
class CurrencyListView(BackendListView):
|
||||
template_name = f"{settings.EXPEPHALON_BACKEND}/currencies/index.html"
|
||||
model = Currency
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["title"] = "Currency Settings"
|
||||
return context
|
||||
|
||||
class CurrencyEditView(BackendUpdateView):
|
||||
template_name = f"{settings.EXPEPHALON_BACKEND}/currencies/update.html"
|
||||
model = Currency
|
||||
success_url = reverse_lazy("currencies")
|
||||
fields = ["name", "code", "symbol", "base", "rate"]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["title"] = "Edit Currency"
|
||||
return context
|
||||
|
||||
class CurrencyDeleteView(BackendDeleteView):
|
||||
template_name = f"{settings.EXPEPHALON_BACKEND}/currencies/delete.html"
|
||||
model = Currency
|
||||
success_url = reverse_lazy("currencies")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["title"] = "Delete Currency"
|
||||
return context
|
||||
|
||||
class CurrencyCreateView(BackendCreateView):
|
||||
template_name = f"{settings.EXPEPHALON_BACKEND}/currencies/create.html"
|
||||
model = Currency
|
||||
success_url = reverse_lazy("currencies")
|
||||
fields = ["name", "code", "symbol", "base", "rate"]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["title"] = "Create Currency"
|
||||
return context
|
|
@ -10,37 +10,37 @@ class InvoiceListView(BackendListView):
|
|||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["title"] = "Brand Settings"
|
||||
context["title"] = "Invoice Settings"
|
||||
return context
|
||||
|
||||
class InvoiceEditView(BackendUpdateView):
|
||||
template_name = f"{settings.EXPEPHALON_BACKEND}/invoices/update.html"
|
||||
model = Invoice
|
||||
success_url = reverse_lazy("brands")
|
||||
success_url = reverse_lazy("invoices")
|
||||
fields = ["name", "logo", "address1", "address2", "zip", "city", "state", "country", "vat_id", "company_id"]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["title"] = "Edit Brand"
|
||||
context["title"] = "Edit Invoice"
|
||||
return context
|
||||
|
||||
class InvoiceDeleteView(BackendDeleteView):
|
||||
template_name = f"{settings.EXPEPHALON_BACKEND}/invoices/delete.html"
|
||||
model = Invoice
|
||||
success_url = reverse_lazy("brands")
|
||||
success_url = reverse_lazy("invoices")
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["title"] = "Delete Brand"
|
||||
context["title"] = "Delete Invoice"
|
||||
return context
|
||||
|
||||
class InvoiceCreateView(BackendCreateView):
|
||||
template_name = f"{settings.EXPEPHALON_BACKEND}/invoices/create.html"
|
||||
model = Invoice
|
||||
success_url = reverse_lazy("brands")
|
||||
success_url = reverse_lazy("invoices")
|
||||
fields = ["name", "logo", "address1", "address2", "zip", "city", "state", "country", "vat_id", "company_id"]
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context["title"] = "Create Brand"
|
||||
context["title"] = "Create Invoice"
|
||||
return context
|
||||
|
|
|
@ -1,19 +1,8 @@
|
|||
from django.forms import TextInput
|
||||
from django.conf import settings
|
||||
from django.templatetags.static import static
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
class ColorPickerWidget(TextInput):
|
||||
class Media:
|
||||
css = {
|
||||
"all": (
|
||||
static("backend/css/colorPicker.css")
|
||||
)
|
||||
}
|
||||
js = (
|
||||
static("backend/scripts/jquery.colorPicker.js")
|
||||
)
|
||||
|
||||
def render(self, name, value, attrs=None, renderer=None):
|
||||
rendered = super().render(name, value, attrs=attrs, renderer=renderer)
|
||||
return rendered + mark_safe(f'<script type="text/javascript">$("#id_{name}").colorPicker();</script>')
|
||||
def __init__(self, attrs={}):
|
||||
attrs["class"] = "colorpicker"
|
||||
super().__init__(attrs)
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
rabbitmq-server
|
||||
memcached
|
||||
git
|
|
@ -52,5 +52,7 @@ RABBITMQ_USER = "guest"
|
|||
RABBITMQ_PASS = "guest"
|
||||
|
||||
# Logging
|
||||
# Set log level to something higher in production - debug might leak sensitive information
|
||||
|
||||
LOG_DIRECTORY = "/var/log/expephalon/"
|
||||
LOGLEVEL = "DEBUG"
|
|
@ -149,6 +149,7 @@ CELERY_CACHE_BACKEND = 'django-cache'
|
|||
CELERY_BROKER_URL = f"amqp://{RABBITMQ_USER}:{RABBITMQ_PASS}@{RABBITMQ_LOCATION}/{RABBITMQ_VHOST}"
|
||||
CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler"
|
||||
CELERY_TASK_RESULT_EXPIRES = 12 * 60 * 60
|
||||
CELERY_WORKER_HIJACK_ROOT_LOGGER = False
|
||||
|
||||
# Auth URLs
|
||||
|
||||
|
@ -165,7 +166,7 @@ except:
|
|||
|
||||
try:
|
||||
with open(os.path.join(LOG_DIRECTORY, "expephalon.log"), "a") as logfile:
|
||||
logfile.write("\n----------\n")
|
||||
logfile.write("\n----------\n\nStarting Expephalon...\n")
|
||||
except:
|
||||
raise Exception(f"Unable to write to log file {os.path.join(LOG_DIRECTORY, 'expephalon.log')}, please make sure the Expephalon user account has sufficient privileges to write to the {LOG_DIRECTORY} directory and all files within it.")
|
||||
|
||||
|
@ -182,7 +183,7 @@ LOGGING = {
|
|||
},
|
||||
'handlers': {
|
||||
'expephalon': {
|
||||
'level': 'DEBUG',
|
||||
'level': LOGLEVEL,
|
||||
'class': 'logging.handlers.TimedRotatingFileHandler',
|
||||
'filename': os.path.join(LOG_DIRECTORY, 'expephalon.log'),
|
||||
'when': 'midnight',
|
||||
|
@ -198,3 +199,9 @@ LOGGING = {
|
|||
},
|
||||
},
|
||||
}
|
||||
|
||||
try:
|
||||
with open(os.path.join(LOG_DIRECTORY, "expephacron.log"), "a") as logfile:
|
||||
pass
|
||||
except:
|
||||
raise Exception(f"Unable to write to log file {os.path.join(LOG_DIRECTORY, 'expephacron.log')}, please make sure the Expephalon user account has sufficient privileges to write to the {LOG_DIRECTORY} directory and all files within it.")
|
||||
|
|
1
ratesapi
Submodule
1
ratesapi
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 0d2d9a491a1649a70107a588857e69e551c019a1
|
|
@ -17,3 +17,4 @@ pyuca
|
|||
git+https://kumig.it/kumisystems/parse_crontab.git
|
||||
django-internationalflavor
|
||||
suds-jurko
|
||||
GitPython
|
|
@ -1 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
celery -A expephalon worker --loglevel=info
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
celery -A expephalon beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler
|
||||
|
|
1
static/backend/scripts/custom.colorPicker.js
Normal file
1
static/backend/scripts/custom.colorPicker.js
Normal file
|
@ -0,0 +1 @@
|
|||
$(".colorpicker").colorPicker({pickerDefault: "58D062"});
|
2
static/backend/scripts/jquery-3.5.1.min.js
vendored
Normal file
2
static/backend/scripts/jquery-3.5.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -349,4 +349,4 @@
|
|||
showHexField: true
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
})($);
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
-->
|
||||
<link href="{% static "backend/css/main.css" %}" rel="stylesheet">
|
||||
<link href="https://fa.kumi.systems/css/all.css" rel="stylesheet">
|
||||
{% block css %}{% endblock %}
|
||||
<script src="{% static "backend/scripts/jquery-3.5.1.min.js" %}"></script>"
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-container app-theme-white body-tabs-shadow fixed-sidebar fixed-header">
|
||||
|
@ -476,5 +478,6 @@
|
|||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="{% static "backend/scripts/main.js" %}"></script>
|
||||
{% block scripts %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
{% extends "backend/base.html" %}
|
||||
{% load bootstrap4 %}
|
||||
{% load static %}
|
||||
{% block css %}
|
||||
<link href="{% static "backend/css/colorPicker.css" %}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="app-page-title">
|
||||
<div class="page-title-wrapper">
|
||||
|
@ -51,7 +55,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
<script type="text/javascript" src="{% static "backend/scripts/jquery.colorPicker.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "backend/scripts/custom.colorPicker.js" %}"></script>
|
||||
{% endblock %}
|
|
@ -43,7 +43,7 @@
|
|||
<tbody>
|
||||
{% for group in object_list %}
|
||||
<tr>
|
||||
<td>{{ group.name }}</td>
|
||||
<td style="color:{{ group.color }};">{{ group.name }}</td>
|
||||
<td><a href="{% url "clientgroups_edit" group.id %}"><i class="fas fa-edit" title="Edit Client Group"></i></a> <a href="{% url "clientgroups_delete" group.id %}"><i style="color: darkred;" class="fas fa-trash-alt" title="Delete Client Group"></i></a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
{% extends "backend/base.html" %}
|
||||
{% load bootstrap4 %}
|
||||
{% load static %}
|
||||
{% block css %}
|
||||
<link href="{% static "backend/css/colorPicker.css" %}" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="app-page-title">
|
||||
<div class="page-title-wrapper">
|
||||
|
@ -51,7 +55,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
<script type="text/javascript" src="{% static "backend/scripts/jquery.colorPicker.js" %}"></script>
|
||||
<script type="text/javascript" src="{% static "backend/scripts/custom.colorPicker.js" %}"></script>
|
||||
{% endblock %}
|
57
templates/backend/currencies/create.html
Normal file
57
templates/backend/currencies/create.html
Normal file
|
@ -0,0 +1,57 @@
|
|||
{% extends "backend/base.html" %}
|
||||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<div class="app-page-title">
|
||||
<div class="page-title-wrapper">
|
||||
<div class="page-title-heading">
|
||||
<div class="page-title-icon">
|
||||
<i class="fa fa-users-cog">
|
||||
</i>
|
||||
</div>
|
||||
<div>Currencies - Create Currency
|
||||
<div class="page-title-subheading">Create a new currency
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-title-actions">
|
||||
<button type="button" data-toggle="tooltip" title="New Currency" data-placement="bottom" class="btn-shadow mr-3 btn btn-success">
|
||||
<i class="fa fa-plus"></i> New Currency
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-lg-0">
|
||||
<div class="mb-3 card">
|
||||
<div class="card-header-tab card-header-tab-animation card-header">
|
||||
<div class="card-header-title">
|
||||
<i class="header-icon lnr-apartment icon-gradient bg-love-kiss"> </i>
|
||||
Create Currency
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active" id="tabs-eg-77">
|
||||
<form method="POST" enctype="multipart/form-data" >
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn-shadow mr-3 btn btn-success">
|
||||
<i class="fa fa-check"></i> Save
|
||||
</button>
|
||||
<a href="{% url "currencies" %}" class="btn-shadow mr-3 btn btn-danger">
|
||||
<i class="fa fa-times"></i> Cancel
|
||||
</a>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
57
templates/backend/currencies/delete.html
Normal file
57
templates/backend/currencies/delete.html
Normal file
|
@ -0,0 +1,57 @@
|
|||
{% extends "backend/base.html" %}
|
||||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<div class="app-page-title">
|
||||
<div class="page-title-wrapper">
|
||||
<div class="page-title-heading">
|
||||
<div class="page-title-icon">
|
||||
<i class="fa fa-database">
|
||||
</i>
|
||||
</div>
|
||||
<div>Currencies - Delete Currency
|
||||
<div class="page-title-subheading">Delete a currency from the system
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-title-actions">
|
||||
<button type="button" data-toggle="tooltip" title="New Brand" data-placement="bottom" class="btn-shadow mr-3 btn btn-success">
|
||||
<i class="fa fa-plus"></i> New Currency
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-lg-0">
|
||||
<div class="mb-3 card">
|
||||
<div class="card-header-tab card-header-tab-animation card-header">
|
||||
<div class="card-header-title">
|
||||
<i class="header-icon lnr-apartment icon-gradient bg-love-kiss"> </i>
|
||||
Deleting {{ object.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active" id="tabs-eg-77">
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
Are you sure you wish to delete {{ object.name }}? Please note that this will fail if the currency has already been used in an invoice.
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn-shadow mr-3 btn btn-success">
|
||||
<i class="fa fa-check"></i> Save
|
||||
</button>
|
||||
<a href="{% url "currencies" %}" class="btn-shadow mr-3 btn btn-danger">
|
||||
<i class="fa fa-times"></i> Cancel
|
||||
</a>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
63
templates/backend/currencies/index.html
Normal file
63
templates/backend/currencies/index.html
Normal file
|
@ -0,0 +1,63 @@
|
|||
{% extends "backend/base.html" %}
|
||||
{% block content %}
|
||||
<div class="app-page-title">
|
||||
<div class="page-title-wrapper">
|
||||
<div class="page-title-heading">
|
||||
<div class="page-title-icon">
|
||||
<i class="fa fa-users-cog">
|
||||
</i>
|
||||
</div>
|
||||
<div>Currencies
|
||||
<div class="page-title-subheading">Create, edit and delete currencies
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-title-actions">
|
||||
<a href="{% url "currencies_create" %}" type="button" data-toggle="tooltip" title="New Currency" data-placement="bottom" class="btn-shadow mr-3 btn btn-success">
|
||||
<i class="fa fa-plus"></i> New Currency
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-lg-0">
|
||||
<div class="mb-3 card">
|
||||
<div class="card-header-tab card-header-tab-animation card-header">
|
||||
<div class="card-header-title">
|
||||
<i class="header-icon lnr-apartment icon-gradient bg-love-kiss"> </i>
|
||||
Active Currencies
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active" id="tabs-eg-77">
|
||||
<div class="card mb-3 widget-chart widget-chart2 text-left w-100">
|
||||
<table class="mb-0 table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Code</th>
|
||||
<th>Symbol</th>
|
||||
<th>Options</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for currency in object_list %}
|
||||
<tr>
|
||||
<td>{{ currency.name }}</td>
|
||||
<td>{{ currency.code }}</td>
|
||||
<td>{{ currency.symbol }}</td>
|
||||
<td><a href="{% url "currencies_edit" currency.id %}"><i class="fas fa-edit" title="Edit Currency"></i></a> <a href="{% url "currencies_delete" currency.id %}"><i style="color: darkred;" class="fas fa-trash-alt" title="Delete Currency"></i></a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
54
templates/backend/currencies/update.html
Normal file
54
templates/backend/currencies/update.html
Normal file
|
@ -0,0 +1,54 @@
|
|||
{% extends "backend/base.html" %}
|
||||
{% load bootstrap4 %}
|
||||
{% block content %}
|
||||
<div class="app-page-title">
|
||||
<div class="page-title-wrapper">
|
||||
<div class="page-title-heading">
|
||||
<div class="page-title-icon">
|
||||
<i class="fa fa-users-cog">
|
||||
</i>
|
||||
</div>
|
||||
<div>Currencies - Edit Currency
|
||||
<div class="page-title-subheading">Edit currency properties
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-title-actions">
|
||||
<button type="button" data-toggle="tooltip" title="New Currency" data-placement="bottom" class="btn-shadow mr-3 btn btn-success">
|
||||
<i class="fa fa-plus"></i> New Currency
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-12 col-lg-0">
|
||||
<div class="mb-3 card">
|
||||
<div class="card-header-tab card-header-tab-animation card-header">
|
||||
<div class="card-header-title">
|
||||
<i class="header-icon lnr-apartment icon-gradient bg-love-kiss"> </i>
|
||||
Editing {{ object.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active" id="tabs-eg-77">
|
||||
<form method="POST" enctype="multipart/form-data" >
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form %}
|
||||
{% buttons %}
|
||||
<button type="submit" class="btn-shadow mr-3 btn btn-success">
|
||||
<i class="fa fa-check"></i> Save
|
||||
</button>
|
||||
<a href="{% url "currencies" %}" class="btn-shadow mr-3 btn btn-danger">
|
||||
<i class="fa fa-times"></i> Cancel
|
||||
</a>
|
||||
{% endbuttons %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
Loading…
Reference in a new issue