Release 6 (devel -> main) #26
13 changed files with 31 additions and 115 deletions
17
README.md
17
README.md
|
@ -15,7 +15,8 @@ You have to bring your own PostgreSQL Database though.
|
||||||
|
|
||||||
## Setup, Installation, Updating and Dependencies
|
## Setup, Installation, Updating and Dependencies
|
||||||
|
|
||||||
see [Setup](docs/Setup.md)
|
You can find the latest releases [here](https://gitlab.com/W13R/drinks-manager/-/releases), but for Installation/Updating, you should consider using Git.
|
||||||
|
For more information see [Setup](docs/Setup.md).
|
||||||
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
@ -28,17 +29,3 @@ see [Configuration](docs/Configuration.md)
|
||||||
After setup, run ```./run.sh help``` to see a help text.
|
After setup, run ```./run.sh help``` to see a help text.
|
||||||
Start the production server with ```./run.sh server```. You can ignore the error message about the "lifespan error".
|
Start the production server with ```./run.sh server```. You can ignore the error message about the "lifespan error".
|
||||||
For more commands, see [Commands](docs/Commands.md).
|
For more commands, see [Commands](docs/Commands.md).
|
||||||
|
|
||||||
|
|
||||||
## Versions
|
|
||||||
|
|
||||||
You can find the latest releases [here](https://gitlab.com/W13R/drinks-manager/-/releases).
|
|
||||||
For Installation/Updating, you should consider using git,
|
|
||||||
though (for more information see [Setup](docs/Setup.md)).
|
|
||||||
|
|
||||||
The releases are versioned after the following scheme:
|
|
||||||
|
|
||||||
`MAJOR`.`MINOR`
|
|
||||||
|
|
||||||
- `MAJOR`: may include **breaking changes** and/or significant new features
|
|
||||||
- `MINOR`: will only include bugfixes and smaller, **non-breaking changes**
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ class CustomDrinkAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
model = Drink
|
model = Drink
|
||||||
form = CustomDrinkForm
|
form = CustomDrinkForm
|
||||||
list_display = ["product_name", "content_litres", "price", "available", "binary_availability", "deleted"]
|
list_display = ["product_name", "content_litres", "price", "available", "do_not_count", "deleted"]
|
||||||
|
|
||||||
adminSite.register(Drink, CustomDrinkAdmin)
|
adminSite.register(Drink, CustomDrinkAdmin)
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ class CustomDrinkForm(forms.ModelForm):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Drink
|
model = Drink
|
||||||
fields = ("product_name", "content_litres", "price", "binary_availability", "available", "deleted")
|
fields = ("product_name", "content_litres", "price", "do_not_count", "available", "deleted")
|
||||||
|
|
||||||
|
|
||||||
class CustomRegisterTransactionForm(forms.ModelForm):
|
class CustomRegisterTransactionForm(forms.ModelForm):
|
||||||
|
|
|
@ -41,10 +41,11 @@ class Drink(models.Model):
|
||||||
available = models.PositiveIntegerField(default=0)
|
available = models.PositiveIntegerField(default=0)
|
||||||
deleted = models.BooleanField(default=False)
|
deleted = models.BooleanField(default=False)
|
||||||
|
|
||||||
# when the following field is true:
|
# when the following field is true, the amount of drinks will
|
||||||
|
# not change and will not be displayed.
|
||||||
# available > 0 -> there is a indefinetly amount of drinks left
|
# available > 0 -> there is a indefinetly amount of drinks left
|
||||||
# available < 1 -> there are no drinks left
|
# available < 1 -> there are no drinks left
|
||||||
binary_availability = models.BooleanField(default=False)
|
do_not_count = models.BooleanField(default=False)
|
||||||
|
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
self.deleted = True
|
self.deleted = True
|
||||||
|
@ -123,7 +124,7 @@ class Order(models.Model):
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
drink = Drink.objects.get(pk=self.drink.pk)
|
drink = Drink.objects.get(pk=self.drink.pk)
|
||||||
if self._state.adding and drink.available > 0:
|
if self._state.adding and drink.available > 0:
|
||||||
if not drink.binary_availability:
|
if not drink.do_not_count:
|
||||||
drink.available -= self.amount
|
drink.available -= self.amount
|
||||||
drink.save()
|
drink.save()
|
||||||
self.product_name = drink.product_name
|
self.product_name = drink.product_name
|
||||||
|
@ -139,7 +140,7 @@ class Order(models.Model):
|
||||||
self.user.balance += self.price_sum
|
self.user.balance += self.price_sum
|
||||||
self.user.save()
|
self.user.save()
|
||||||
drink = Drink.objects.get(pk=self.drink.pk)
|
drink = Drink.objects.get(pk=self.drink.pk)
|
||||||
if not drink.binary_availability:
|
if not drink.do_not_count:
|
||||||
drink.available += self.amount
|
drink.available += self.amount
|
||||||
drink.save()
|
drink.save()
|
||||||
super().delete(*args, **kwargs)
|
super().delete(*args, **kwargs)
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
<ul class="availableDrinksList">
|
<ul class="availableDrinksList">
|
||||||
{% for drink in available_drinks %}
|
{% for drink in available_drinks %}
|
||||||
{% if drink.binary_availability %}
|
{% if drink.do_not_count %}
|
||||||
<li>
|
<li>
|
||||||
<a class="button" href="/order/{{ drink.id }}">
|
<a class="button" href="/order/{{ drink.id }}">
|
||||||
<span>{{ drink }}</span>
|
<span>{{ drink }}</span>
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<div class="column" id="pricePerDrink" data-drink-price="{% localize off %}{{ drink.price }}{% endlocalize %}">{{ drink.price }}</div>
|
<div class="column" id="pricePerDrink" data-drink-price="{% localize off %}{{ drink.price }}{% endlocalize %}">{{ drink.price }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if not drink.binary_availability %}
|
{% if not drink.do_not_count %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="column">{% translate "Available" %}:</div>
|
<div class="column">{% translate "Available" %}:</div>
|
||||||
<div class="column">{{ drink.available }}</div>
|
<div class="column">{{ drink.available }}</div>
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<span class="customNumberInput">
|
<span class="customNumberInput">
|
||||||
<button type="button" class="customNumberInput-minus" id="numberOfDrinksBtnA">-</button>
|
<button type="button" class="customNumberInput-minus" id="numberOfDrinksBtnA">-</button>
|
||||||
{% if drink.binary_availability %}
|
{% if drink.do_not_count %}
|
||||||
<input type="number" class="customNumberInputField" name="numberOfDrinks" id="numberOfDrinks"
|
<input type="number" class="customNumberInputField" name="numberOfDrinks" id="numberOfDrinks"
|
||||||
min="1" max="100" value="1">
|
min="1" max="100" value="1">
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
|
@ -20,37 +20,9 @@
|
||||||
|
|
||||||
<div class="mainContainer">
|
<div class="mainContainer">
|
||||||
|
|
||||||
<div class="dropDownMenu" id="statisticsDropDownMenu">
|
|
||||||
<button class="dropDownButton" id="statisticsDropDownMenuButton">
|
|
||||||
<div>
|
|
||||||
{% translate "Choose" %}
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<div class="dropDownList">
|
|
||||||
<button class="sChoice dropDownChoice" data-statistics_div="noyopd">
|
|
||||||
{% translate "Your orders per drink" %}
|
|
||||||
</button>
|
|
||||||
<button class="sChoice dropDownChoice" data-statistics_div="yopwd">
|
|
||||||
{% translate "Your orders per weekday" %}
|
|
||||||
</button>
|
|
||||||
<button class="sChoice dropDownChoice" data-statistics_div="yopml12m">
|
|
||||||
{% translate "Your orders per month (last 12 months)" %}
|
|
||||||
</button>
|
|
||||||
<button class="sChoice dropDownChoice" data-statistics_div="noaopd">
|
|
||||||
{% translate "All orders per drink" %}
|
|
||||||
</button>
|
|
||||||
<button class="sChoice dropDownChoice" data-statistics_div="aopwd">
|
|
||||||
{% translate "All orders per weekday" %}
|
|
||||||
</button>
|
|
||||||
<button class="sChoice dropDownChoice" data-statistics_div="aopml12m">
|
|
||||||
{% translate "All orders per month (last 12 months)" %}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="tablesContainer">
|
<div class="tablesContainer">
|
||||||
|
|
||||||
<div id="noyopd" class="statisticsTable nodisplay">
|
<div id="noyopd" class="statisticsTable">
|
||||||
<h1>{% translate "Your orders per drink" %}</h1>
|
<h1>{% translate "Your orders per drink" %}</h1>
|
||||||
{% if noyopd %}
|
{% if noyopd %}
|
||||||
<table>
|
<table>
|
||||||
|
@ -70,7 +42,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="noaopd" class="statisticsTable nodisplay">
|
<div id="noaopd" class="statisticsTable">
|
||||||
<h1>{% translate "All orders per drink" %}</h1>
|
<h1>{% translate "All orders per drink" %}</h1>
|
||||||
{% if noaopd %}
|
{% if noaopd %}
|
||||||
<table>
|
<table>
|
||||||
|
@ -90,7 +62,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="yopml12m" class="statisticsTable nodisplay">
|
<div id="yopml12m" class="statisticsTable">
|
||||||
<h1>{% translate "Your orders per month (last 12 months)" %}</h1>
|
<h1>{% translate "Your orders per month (last 12 months)" %}</h1>
|
||||||
{% if yopml12m %}
|
{% if yopml12m %}
|
||||||
<table>
|
<table>
|
||||||
|
@ -110,7 +82,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="aopml12m" class="statisticsTable nodisplay">
|
<div id="aopml12m" class="statisticsTable">
|
||||||
<h1>{% translate "All orders per month (last 12 months)" %}</h1>
|
<h1>{% translate "All orders per month (last 12 months)" %}</h1>
|
||||||
{% if aopml12m %}
|
{% if aopml12m %}
|
||||||
<table>
|
<table>
|
||||||
|
@ -130,7 +102,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="yopwd" class="statisticsTable nodisplay">
|
<div id="yopwd" class="statisticsTable">
|
||||||
<h1>{% translate "Your orders per weekday" %}</h1>
|
<h1>{% translate "Your orders per weekday" %}</h1>
|
||||||
{% if yopwd %}
|
{% if yopwd %}
|
||||||
<table>
|
<table>
|
||||||
|
@ -150,7 +122,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="aopwd" class="statisticsTable nodisplay">
|
<div id="aopwd" class="statisticsTable">
|
||||||
<h1>{% translate "All orders per weekday" %}</h1>
|
<h1>{% translate "All orders per weekday" %}</h1>
|
||||||
{% if aopwd %}
|
{% if aopwd %}
|
||||||
<table>
|
<table>
|
||||||
|
@ -174,6 +146,4 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/static/js/statistics.js"></script>
|
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -24,11 +24,10 @@
|
||||||
<div class="dropDownList">
|
<div class="dropDownList">
|
||||||
<a class="button dropDownChoice" id="navBarBtnHistory" href="/history">{% translate "History" %}</a>
|
<a class="button dropDownChoice" id="navBarBtnHistory" href="/history">{% translate "History" %}</a>
|
||||||
<a class="button dropDownChoice" id="navBarBtnStatistics" href="/statistics">{% translate "Statistics" %}</a>
|
<a class="button dropDownChoice" id="navBarBtnStatistics" href="/statistics">{% translate "Statistics" %}</a>
|
||||||
{% if user.is_superuser %}
|
{% if user.is_superuser or user.is_staff %}
|
||||||
<a class="button dropDownChoice" href="/admin/">Admin Panel</a>
|
<a class="button dropDownChoice" href="/admin/">Admin Panel</a>
|
||||||
{% else %}
|
|
||||||
<a class="button dropDownChoice" href="/accounts/password_change/">{% translate "Change Password" %}</a>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<a class="button dropDownChoice" href="/accounts/password_change/">{% translate "Change Password" %}</a>
|
||||||
<a class="button dropDownChoice" href="/accounts/logout">{% translate "Logout" %}</a>
|
<a class="button dropDownChoice" href="/accounts/logout">{% translate "Logout" %}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -126,7 +126,7 @@ def api_order_drink(request):
|
||||||
|
|
||||||
drink = Drink.objects.get(pk=drinkID)
|
drink = Drink.objects.get(pk=drinkID)
|
||||||
|
|
||||||
if ((drink.binary_availability and drink.available > 0) or (drink.available >= amount)) and not drink.deleted:
|
if ((drink.do_not_count and drink.available > 0) or (drink.available >= amount)) and not drink.deleted:
|
||||||
Order.objects.create(drink=drink, user=user, amount=amount)
|
Order.objects.create(drink=drink, user=user, amount=amount)
|
||||||
return HttpResponse("success", status=200)
|
return HttpResponse("success", status=200)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
|
|
||||||
export DJANGO_SK_ABS_FP="$(pwd)/config/secret_key.txt"
|
export DJANGO_SK_ABS_FP="$(pwd)/config/secret_key.txt"
|
||||||
export STATIC_FILES="$(pwd)/static/"
|
export STATIC_FILES="$(pwd)/static/"
|
||||||
export APP_VERSION="5.0"
|
export APP_VERSION="6"
|
||||||
export PYTHONPATH="$(pwd)/packages/"
|
export PYTHONPATH="$(pwd)/packages/"
|
||||||
|
|
|
@ -1,24 +1,21 @@
|
||||||
.mainContainer {
|
.mainContainer {
|
||||||
|
min-width: 70vw;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: start;
|
justify-content: start;
|
||||||
width: 100%;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
}
|
||||||
.statsHeading {
|
.statsHeading {
|
||||||
min-width: max-content;
|
min-width: max-content;
|
||||||
margin-left: 2rem;
|
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
.tablesContainer {
|
.tablesContainer {
|
||||||
position: absolute;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: start;
|
justify-content: start;
|
||||||
width: 95%;
|
width: 95%;
|
||||||
margin-top: 5rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
.statisticsTable {
|
.statisticsTable {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
|
@ -46,9 +43,6 @@
|
||||||
.statisticsTable td:last-child {
|
.statisticsTable td:last-child {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
#statisticsDropDownMenu .dropDownList {
|
|
||||||
z-index: 195;
|
|
||||||
}
|
|
||||||
@media only screen and (max-width: 700px) {
|
@media only screen and (max-width: 700px) {
|
||||||
.statisticsTable h1 {
|
.statisticsTable h1 {
|
||||||
min-width: 90vw;
|
min-width: 90vw;
|
||||||
|
|
|
@ -21,6 +21,9 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|
||||||
let number_of_drinks = parseFloat(order_number_of_drinks_input.value);
|
let number_of_drinks = parseFloat(order_number_of_drinks_input.value);
|
||||||
|
if (isNaN(number_of_drinks)) {
|
||||||
|
number_of_drinks = 1;
|
||||||
|
}
|
||||||
let calculated_sum = order_price_per_drink * number_of_drinks;
|
let calculated_sum = order_price_per_drink * number_of_drinks;
|
||||||
order_sum_element.innerText = new Intl.NumberFormat(undefined, {minimumFractionDigits: 2}).format(calculated_sum);
|
order_sum_element.innerText = new Intl.NumberFormat(undefined, {minimumFractionDigits: 2}).format(calculated_sum);
|
||||||
|
|
||||||
|
@ -41,6 +44,10 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
|
||||||
event.preventDefault(); // Don't do the default submit action!
|
event.preventDefault(); // Don't do the default submit action!
|
||||||
|
|
||||||
|
if (isNaN(parseFloat(order_number_of_drinks_input.value))) {
|
||||||
|
order_number_of_drinks_input.value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
let xhr = new XMLHttpRequest();
|
let xhr = new XMLHttpRequest();
|
||||||
let formData = new FormData(order_form);
|
let formData = new FormData(order_form);
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
{
|
|
||||||
|
|
||||||
let statistics_dropdown_choices;
|
|
||||||
let statistics_tables;
|
|
||||||
|
|
||||||
let dropDownMenuActive = false;
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
|
|
||||||
// elements
|
|
||||||
let statistics_dropdown_menu = document.getElementById("statisticsDropDownMenu");
|
|
||||||
let statistics_dropdown_menu_button = document.getElementById("statisticsDropDownMenuButton");
|
|
||||||
statistics_dropdown_choices = [...statistics_dropdown_menu.getElementsByClassName("sChoice")];
|
|
||||||
statistics_tables = [...document.getElementsByClassName("statisticsTable")];
|
|
||||||
|
|
||||||
statistics_dropdown_menu_button.addEventListener("click", () => {
|
|
||||||
if (statistics_dropdown_menu.classList.contains("dropDownVisible")) {
|
|
||||||
statistics_dropdown_menu.classList.remove("dropDownVisible");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
statistics_dropdown_menu.classList.add("dropDownVisible");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
statistics_dropdown_choices.forEach(element => {
|
|
||||||
|
|
||||||
element.addEventListener("click", () => {
|
|
||||||
changeStatisticsChoice(element.innerText, element.dataset.statistics_div);
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
function changeStatisticsChoice(choice_name, div_id) {
|
|
||||||
statistics_tables.forEach(element => {
|
|
||||||
element.classList.add("nodisplay");
|
|
||||||
})
|
|
||||||
document.getElementById(div_id).classList.remove("nodisplay");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue