fnschool 20251016.81138.855__py3-none-any.whl → 20251018.80328.837__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fnschool might be problematic. Click here for more details.
- fnschoo1/__init__.py +1 -1
- fnschoo1/canteen/models.py +5 -0
- fnschoo1/canteen/templates/canteen/category/create.html +3 -1
- fnschoo1/canteen/templates/canteen/category/delete.html +3 -1
- fnschoo1/canteen/templates/canteen/category/update.html +3 -1
- fnschoo1/canteen/templates/canteen/consumption/create.html +38 -14
- fnschoo1/canteen/templates/canteen/ingredient/create.html +6 -2
- fnschoo1/canteen/templates/canteen/ingredient/create_one.html +3 -1
- fnschoo1/canteen/templates/canteen/ingredient/delete.html +3 -1
- fnschoo1/canteen/templates/canteen/ingredient/list.html +3 -1
- fnschoo1/canteen/templates/canteen/ingredient/update.html +3 -1
- fnschoo1/canteen/templates/canteen/meal_type/create.html +3 -1
- fnschoo1/canteen/templates/canteen/meal_type/delete.html +3 -1
- fnschoo1/canteen/templates/canteen/meal_type/update.html +3 -1
- fnschoo1/canteen/views.py +29 -5
- fnschoo1/canteen/workbook/generate.py +569 -32
- fnschoo1/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
- fnschoo1/profiles/templates/profiles/create.html +3 -1
- fnschoo1/profiles/templates/profiles/detail.html +3 -1
- fnschoo1/profiles/templates/profiles/edit.html +3 -1
- fnschoo1/profiles/templates/profiles/log_in.html +3 -1
- fnschoo1/templates/includes/_footer.html +12 -4
- fnschoo1/templates/includes/_paginator.html +3 -1
- {fnschool-20251016.81138.855.dist-info → fnschool-20251018.80328.837.dist-info}/METADATA +1 -1
- {fnschool-20251016.81138.855.dist-info → fnschool-20251018.80328.837.dist-info}/RECORD +34 -34
- {fnschool-20251016.81138.855.dist-info → fnschool-20251018.80328.837.dist-info}/SOURCES.txt.py +0 -0
- {fnschool-20251016.81138.855.dist-info → fnschool-20251018.80328.837.dist-info}/WHEEL +0 -0
- {fnschool-20251016.81138.855.dist-info → fnschool-20251018.80328.837.dist-info}/dependency_links.txt.py +0 -0
- {fnschool-20251016.81138.855.dist-info → fnschool-20251018.80328.837.dist-info}/entry_points.txt +0 -0
- {fnschool-20251016.81138.855.dist-info → fnschool-20251018.80328.837.dist-info}/entry_points.txt.py +0 -0
- {fnschool-20251016.81138.855.dist-info → fnschool-20251018.80328.837.dist-info}/licenses/LICENSE +0 -0
- {fnschool-20251016.81138.855.dist-info → fnschool-20251018.80328.837.dist-info}/requires.txt.py +0 -0
- {fnschool-20251016.81138.855.dist-info → fnschool-20251018.80328.837.dist-info}/top_level.txt +0 -0
- {fnschool-20251016.81138.855.dist-info → fnschool-20251018.80328.837.dist-info}/top_level.txt.py +0 -0
fnschoo1/__init__.py
CHANGED
fnschoo1/canteen/models.py
CHANGED
|
@@ -113,6 +113,10 @@ class Ingredient(models.Model):
|
|
|
113
113
|
default=False, verbose_name=_("Is Ingredient Disabled")
|
|
114
114
|
)
|
|
115
115
|
|
|
116
|
+
def __init__(self, *args, **kwargs):
|
|
117
|
+
super().__init__(*args, **kwargs)
|
|
118
|
+
self.quantity_used = Decimal("0")
|
|
119
|
+
|
|
116
120
|
@property
|
|
117
121
|
def unit_price(self):
|
|
118
122
|
if self.quantity > 0:
|
|
@@ -186,6 +190,7 @@ class Consumption(models.Model):
|
|
|
186
190
|
)
|
|
187
191
|
|
|
188
192
|
class Meta:
|
|
193
|
+
|
|
189
194
|
verbose_name = _("Consumption Record")
|
|
190
195
|
verbose_name_plural = _("Consumption Records")
|
|
191
196
|
ordering = ["-date_of_using"]
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
{{ form|crispy }}
|
|
12
12
|
<div class="py-3 fixed-bottom text-end bg-dark">
|
|
13
13
|
<button type="submit" class="btn btn-primary">{% trans "Save" %}</button>
|
|
14
|
-
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
14
|
+
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
15
|
+
{% trans "Cancel" %}
|
|
16
|
+
</button>
|
|
15
17
|
</div>
|
|
16
18
|
</form>
|
|
17
19
|
{% endblock %}
|
|
@@ -55,7 +55,9 @@
|
|
|
55
55
|
style="display: inline">
|
|
56
56
|
{% csrf_token %}
|
|
57
57
|
<button type="submit" class="btn btn-danger">{% trans 'Delete' %}</button>
|
|
58
|
-
<button type="button" class="btn btn-primary" onclick="window.close();">
|
|
58
|
+
<button type="button" class="btn btn-primary" onclick="window.close();">
|
|
59
|
+
{% trans "Cancel" %}
|
|
60
|
+
</button>
|
|
59
61
|
</form>
|
|
60
62
|
</div>
|
|
61
63
|
<script>
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
{% csrf_token %} {{ form|crispy }}
|
|
18
18
|
<div class="py-3 fixed-bottom text-end bg-dark">
|
|
19
19
|
<button type="submit" class="btn btn-primary">{% trans "Save" %}</button>
|
|
20
|
-
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
20
|
+
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
21
|
+
{% trans "Cancel" %}
|
|
22
|
+
</button>
|
|
21
23
|
</div>
|
|
22
24
|
</form>
|
|
23
25
|
{% endblock %}
|
|
@@ -9,10 +9,14 @@
|
|
|
9
9
|
<div class="container">
|
|
10
10
|
<div class="row justify-content-end">
|
|
11
11
|
<button class="btn btn-outline-success col-md-1 col-lg-1 col-2 mx-2"
|
|
12
|
-
onclick="list_consumptions_by_week();">
|
|
12
|
+
onclick="list_consumptions_by_week();">
|
|
13
|
+
{% trans "Consume by Week" %}
|
|
14
|
+
</button>
|
|
13
15
|
|
|
14
16
|
<button class="btn btn-outline-success col-md-1 col-lg-1 col-2"
|
|
15
|
-
onclick="list_consumptions_rapidly();">
|
|
17
|
+
onclick="list_consumptions_rapidly();">
|
|
18
|
+
{% trans "Rapid Consumption" %}
|
|
19
|
+
</button>
|
|
16
20
|
|
|
17
21
|
<a class="btn btn-success col-md-1 col-lg-1 col-2 mx-2"
|
|
18
22
|
target="canteen_list_categories"
|
|
@@ -49,10 +53,10 @@
|
|
|
49
53
|
{% for date_h in date_range %}
|
|
50
54
|
<th data-date_of_using="{{ date_h }}" class="consumption-date">
|
|
51
55
|
{{ date_h }}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
{% for meal_type in meal_types %}
|
|
57
|
+
<br />
|
|
58
|
+
|
|
|
59
|
+
{% endfor %}
|
|
56
60
|
</th>
|
|
57
61
|
{% empty %}
|
|
58
62
|
<th></th>
|
|
@@ -65,6 +69,9 @@
|
|
|
65
69
|
data-ingredient_id="{{ ingredient.id }}"
|
|
66
70
|
data-ingredient_name="{{ ingredient.name }}"
|
|
67
71
|
data-ingredient_quantity="{{ ingredient.quantity }}"
|
|
72
|
+
data-ingredient_quantity_used="{{ ingredient.quantity_used }}"
|
|
73
|
+
data-ingredient_remaining_quantity="{{ ingredient.remaining_quantity }}"
|
|
74
|
+
data-ingredient_consuming_quantity="{{ ingredient.consuming_quantity }}"
|
|
68
75
|
data-ingredient_total_price="{{ ingredient.total_price }}"
|
|
69
76
|
data-ingredient_meal_type="{{ ingredient.meal_type }}"
|
|
70
77
|
data-ingredient_quantity_unit_name="{{ ingredient.quantity_unit_name }}"
|
|
@@ -73,16 +80,15 @@
|
|
|
73
80
|
<td title="{% blocktrans with storage_date=ingredient.storage_date %}Storaged on {{ storage_date }} .{% endblocktrans %}"
|
|
74
81
|
class="">
|
|
75
82
|
<div class='ingredient-progress'
|
|
76
|
-
style="width:{% widthratio ingredient.remaining_quantity ingredient.quantity 100 %}%"
|
|
83
|
+
style="width:{% widthratio ingredient.remaining_quantity ingredient.quantity 100 %}%">
|
|
84
|
+
</div>
|
|
77
85
|
{{ ingredient.name }}
|
|
78
|
-
{% if ingredient.meal_type %}
|
|
86
|
+
{% if ingredient.meal_type != meal_type_name_0 %}
|
|
79
87
|
<br />
|
|
80
88
|
({{ ingredient.meal_type }})
|
|
81
89
|
{% endif %}
|
|
82
90
|
</td>
|
|
83
|
-
<td name="remaining_{{ ingredient.id }}">
|
|
84
|
-
{{ ingredient.quantity }}-{{ ingredient.consuming_quantity }}={{ ingredient.remaining_quantity }}
|
|
85
|
-
</td>
|
|
91
|
+
<td name="remaining_{{ ingredient.id }}"></td>
|
|
86
92
|
</tr>
|
|
87
93
|
{% empty %}
|
|
88
94
|
<tr>{% trans "No ingredient found." %}</tr>
|
|
@@ -92,7 +98,9 @@
|
|
|
92
98
|
</div>
|
|
93
99
|
<div class="">
|
|
94
100
|
<button onclick="generate_spreadsheet();"
|
|
95
|
-
class="btn btn-submit-consumptions btn-success float-end">
|
|
101
|
+
class="btn btn-submit-consumptions btn-success float-end">
|
|
102
|
+
{% trans "Generate Spreadsheet" %}
|
|
103
|
+
</button>
|
|
96
104
|
<select class="workbook-month-select form-select float-end mx-2"
|
|
97
105
|
style="width:118px"></select>
|
|
98
106
|
</div>
|
|
@@ -112,6 +120,20 @@
|
|
|
112
120
|
|
|
113
121
|
var dont_submit = false
|
|
114
122
|
|
|
123
|
+
$(document).ready(function() {
|
|
124
|
+
$(ingredient_ids).each(function(index, ingredient_id) {
|
|
125
|
+
var td = $(`td[name='remaining_${ingredient_id}']`)
|
|
126
|
+
var tr = $(td.closest("tr"))
|
|
127
|
+
var ingredient_quantity = parseInt(tr.data("ingredient_quantity")) || 0
|
|
128
|
+
var ingredient_quantity_used = parseInt(tr.data("ingredient_quantity_used")) || 0
|
|
129
|
+
var ingredient_consuming_quantity = parseInt(tr.data("ingredient_consuming_quantity")) || 0
|
|
130
|
+
var ingredient_remaining_quantity = parseInt(tr.data("ingredient_remaining_quantity")) || 0
|
|
131
|
+
td.text(
|
|
132
|
+
`${ingredient_quantity-ingredient_quantity_used}-${ingredient_consuming_quantity-ingredient_quantity_used}=${ingredient_remaining_quantity}`
|
|
133
|
+
)
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
});
|
|
115
137
|
|
|
116
138
|
function list_consumptions_rapidly() {
|
|
117
139
|
query = {
|
|
@@ -216,8 +238,10 @@
|
|
|
216
238
|
|
|
217
239
|
function amount_used_input_blur(element) {
|
|
218
240
|
element = $(element)
|
|
219
|
-
var ingredient_quantity = element.closest('tr').data("ingredient_quantity")
|
|
220
|
-
|
|
241
|
+
var ingredient_quantity = parseInt(element.closest('tr').data("ingredient_quantity")) || 0
|
|
242
|
+
var ingredient_quantity_used = parseInt(element.closest("tr").data("ingredient_quantity_used")) || 0
|
|
243
|
+
ingredient_quantity = ingredient_quantity - ingredient_quantity_used
|
|
244
|
+
|
|
221
245
|
var $consumption_form = element.closest("form")
|
|
222
246
|
var amount_used = parseInt($consumption_form.data("amount_used")) || 0
|
|
223
247
|
var new_amount_used = parseInt($.trim(element.val())) || 0
|
|
@@ -12,8 +12,12 @@
|
|
|
12
12
|
<form method="post" enctype="multipart/form-data">
|
|
13
13
|
{% csrf_token %} {{ form|crispy }}
|
|
14
14
|
<div class="py-3 fixed-bottom text-end bg-dark">
|
|
15
|
-
<button type="submit button" class="btn btn-outline-primary">
|
|
16
|
-
|
|
15
|
+
<button type="submit button" class="btn btn-outline-primary">
|
|
16
|
+
{% trans "Upload" %}
|
|
17
|
+
</button>
|
|
18
|
+
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
19
|
+
{% trans "Cancel" %}
|
|
20
|
+
</button>
|
|
17
21
|
</div>
|
|
18
22
|
</form>
|
|
19
23
|
{% endblock %}
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
{{ form|crispy }}
|
|
12
12
|
<div class="py-3 fixed-bottom text-end bg-dark">
|
|
13
13
|
<button type="submit" class="btn btn-primary">{% trans "Save" %}</button>
|
|
14
|
-
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
14
|
+
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
15
|
+
{% trans "Cancel" %}
|
|
16
|
+
</button>
|
|
15
17
|
</div>
|
|
16
18
|
</form>
|
|
17
19
|
{% endblock %}
|
|
@@ -32,7 +32,9 @@
|
|
|
32
32
|
style="display: inline">
|
|
33
33
|
{% csrf_token %}
|
|
34
34
|
<button type="submit" class="btn btn-danger">{% trans 'Delete' %}</button>
|
|
35
|
-
<button type="button" class="btn btn-primary" onclick="window.close();">
|
|
35
|
+
<button type="button" class="btn btn-primary" onclick="window.close();">
|
|
36
|
+
{% trans "Cancel" %}
|
|
37
|
+
</button>
|
|
36
38
|
</form>
|
|
37
39
|
</div>
|
|
38
40
|
<script>
|
|
@@ -63,7 +63,9 @@
|
|
|
63
63
|
class="form-check-input"
|
|
64
64
|
id="ingredient_free_nark_{{ ingredient.id }}" />
|
|
65
65
|
<label class="form-check-label"
|
|
66
|
-
for="ingredient_free_nark_{{ ingredient.id }}">
|
|
66
|
+
for="ingredient_free_nark_{{ ingredient.id }}">
|
|
67
|
+
{{ forloop.counter }}
|
|
68
|
+
</label>
|
|
67
69
|
</div>
|
|
68
70
|
</th>
|
|
69
71
|
<td>{{ ingredient.storage_date }}</td>
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
{% csrf_token %} {{ form|crispy }}
|
|
18
18
|
<div class="py-3 fixed-bottom text-end bg-dark">
|
|
19
19
|
<button type="submit" class="btn btn-primary">{% trans "Save" %}</button>
|
|
20
|
-
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
20
|
+
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
21
|
+
{% trans "Cancel" %}
|
|
22
|
+
</button>
|
|
21
23
|
</div>
|
|
22
24
|
</form>
|
|
23
25
|
{% endblock %}
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
{{ form|crispy }}
|
|
12
12
|
<div class="py-3 fixed-bottom text-end bg-dark">
|
|
13
13
|
<button type="submit" class="btn btn-primary">{% trans "Save" %}</button>
|
|
14
|
-
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
14
|
+
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
15
|
+
{% trans "Cancel" %}
|
|
16
|
+
</button>
|
|
15
17
|
</div>
|
|
16
18
|
</form>
|
|
17
19
|
{% endblock %}
|
|
@@ -47,7 +47,9 @@
|
|
|
47
47
|
style="display: inline">
|
|
48
48
|
{% csrf_token %}
|
|
49
49
|
<button type="submit" class="btn btn-danger">{% trans 'Delete' %}</button>
|
|
50
|
-
<button type="button" class="btn btn-primary" onclick="window.close();">
|
|
50
|
+
<button type="button" class="btn btn-primary" onclick="window.close();">
|
|
51
|
+
{% trans "Cancel" %}
|
|
52
|
+
</button>
|
|
51
53
|
</form>
|
|
52
54
|
</div>
|
|
53
55
|
<script>
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
{% csrf_token %} {{ form|crispy }}
|
|
18
18
|
<div class="py-3 fixed-bottom text-end bg-dark">
|
|
19
19
|
<button type="submit" class="btn btn-primary">{% trans "Save" %}</button>
|
|
20
|
-
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
20
|
+
<button type="button" class="btn btn-danger" onclick="window.close();">
|
|
21
|
+
{% trans "Cancel" %}
|
|
22
|
+
</button>
|
|
21
23
|
</div>
|
|
22
24
|
</form>
|
|
23
25
|
{% endblock %}
|
fnschoo1/canteen/views.py
CHANGED
|
@@ -57,6 +57,9 @@ from .forms import (
|
|
|
57
57
|
from .models import Category, Consumption, Ingredient, MealType
|
|
58
58
|
|
|
59
59
|
# Create your views here.
|
|
60
|
+
|
|
61
|
+
meal_type_name_0 = _("Meal type 0")
|
|
62
|
+
|
|
60
63
|
decimal_prec = getattr(settings, "DECIMAL_PREC", 2)
|
|
61
64
|
|
|
62
65
|
storage_date_header = (
|
|
@@ -197,6 +200,15 @@ def create_consumptions(request, ingredient_id=None):
|
|
|
197
200
|
consumptions = ingredient.consumptions.filter(
|
|
198
201
|
Q(is_disabled=False)
|
|
199
202
|
).all()
|
|
203
|
+
|
|
204
|
+
consumptions_len = len(consumptions)
|
|
205
|
+
for c_index in range(consumptions_len):
|
|
206
|
+
consumption = consumptions[c_index]
|
|
207
|
+
for c0_index in range(c_index + 1, consumptions_len):
|
|
208
|
+
consumption0 = consumptions[c0_index]
|
|
209
|
+
if consumption.date_of_using == consumption0.date_of_using:
|
|
210
|
+
consumption.delete()
|
|
211
|
+
|
|
200
212
|
consumption_dates = list(set([c.date_of_using for c in consumptions]))
|
|
201
213
|
|
|
202
214
|
for per_day in date_range:
|
|
@@ -206,9 +218,6 @@ def create_consumptions(request, ingredient_id=None):
|
|
|
206
218
|
c for c in consumptions if c.date_of_using == per_day
|
|
207
219
|
]
|
|
208
220
|
consumption = consumptions_per_day[0]
|
|
209
|
-
if len(consumptions_per_day) > 1:
|
|
210
|
-
for c in consumptions_per_day[1:]:
|
|
211
|
-
c.delete()
|
|
212
221
|
|
|
213
222
|
else:
|
|
214
223
|
consumption = Consumption()
|
|
@@ -239,8 +248,7 @@ def create_consumptions(request, ingredient_id=None):
|
|
|
239
248
|
) == "true" or not by_week
|
|
240
249
|
|
|
241
250
|
queries = (
|
|
242
|
-
Q(
|
|
243
|
-
& Q(storage_date__lte=date_end)
|
|
251
|
+
Q(storage_date__lte=date_end)
|
|
244
252
|
& Q(user=request.user)
|
|
245
253
|
& Q(is_disabled=False)
|
|
246
254
|
& Q(is_ignorable=False)
|
|
@@ -266,6 +274,13 @@ def create_consumptions(request, ingredient_id=None):
|
|
|
266
274
|
{"ingredients": ingredients, "date_range": date_range},
|
|
267
275
|
)
|
|
268
276
|
|
|
277
|
+
ingredients = [
|
|
278
|
+
i
|
|
279
|
+
for i in ingredients
|
|
280
|
+
if i.get_remaining_quantity(date_end) > 0
|
|
281
|
+
or i.storage_date >= date_start
|
|
282
|
+
]
|
|
283
|
+
|
|
269
284
|
ingredients_pinned = []
|
|
270
285
|
ingredients_unpinned = []
|
|
271
286
|
categories_top = Category.objects.filter(
|
|
@@ -282,6 +297,9 @@ def create_consumptions(request, ingredient_id=None):
|
|
|
282
297
|
|
|
283
298
|
ingredients = ingredients_pinned + ingredients_unpinned
|
|
284
299
|
|
|
300
|
+
for ingredient in ingredients:
|
|
301
|
+
ingredient.quantity_used = ingredient.get_consuming_quantity(date_start)
|
|
302
|
+
|
|
285
303
|
date_range_cp = date_range
|
|
286
304
|
date_range_cp = [d.strftime("%Y-%m-%d") for d in date_range]
|
|
287
305
|
meal_types = list(set([i.meal_type.name for i in ingredients]))
|
|
@@ -298,6 +316,7 @@ def create_consumptions(request, ingredient_id=None):
|
|
|
298
316
|
"ingredient_ids": ingredient_ids,
|
|
299
317
|
"months": months,
|
|
300
318
|
"storage_date_start": date_start,
|
|
319
|
+
"meal_type_name_0": meal_type_name_0,
|
|
301
320
|
},
|
|
302
321
|
)
|
|
303
322
|
|
|
@@ -508,6 +527,11 @@ def create_ingredients(request):
|
|
|
508
527
|
for index, row in df.iterrows():
|
|
509
528
|
category_name = row[category_header[0]]
|
|
510
529
|
meal_type_name = row[meal_type_header[0]]
|
|
530
|
+
meal_type_name = (
|
|
531
|
+
meal_type_name_0
|
|
532
|
+
if meal_type_name is np.nan
|
|
533
|
+
else meal_type_name
|
|
534
|
+
)
|
|
511
535
|
|
|
512
536
|
category = Category.objects.filter(
|
|
513
537
|
Q(name=category_name) & Q(user=request.user)
|