fnschool 20251016.81833.820__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 +4 -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 +31 -30
- 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 +11 -2
- fnschoo1/canteen/workbook/generate.py +545 -22
- 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.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/METADATA +1 -1
- {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/RECORD +34 -34
- {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/SOURCES.txt.py +0 -0
- {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/WHEEL +0 -0
- {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/dependency_links.txt.py +0 -0
- {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/entry_points.txt +0 -0
- {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/entry_points.txt.py +0 -0
- {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/licenses/LICENSE +0 -0
- {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/requires.txt.py +0 -0
- {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/top_level.txt +0 -0
- {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/top_level.txt.py +0 -0
|
@@ -208,8 +208,10 @@ class CanteenWorkBook:
|
|
|
208
208
|
)
|
|
209
209
|
self.surplus_sheet = self.wb.create_sheet(title=_("Sheet Surplus"))
|
|
210
210
|
self.center_alignment = Alignment(
|
|
211
|
-
horizontal="center", vertical="center"
|
|
211
|
+
horizontal="center", vertical="center", wrap_text=True
|
|
212
212
|
)
|
|
213
|
+
self.left_alignment = Alignment(horizontal="left", vertical="center")
|
|
214
|
+
|
|
213
215
|
self.thin_border = Border(
|
|
214
216
|
left=Side(style="thin"),
|
|
215
217
|
right=Side(style="thin"),
|
|
@@ -222,6 +224,7 @@ class CanteenWorkBook:
|
|
|
222
224
|
self.font_14 = Font(size=14)
|
|
223
225
|
self.font_16 = Font(size=16)
|
|
224
226
|
self.font_16_bold = Font(size=16, bold=True)
|
|
227
|
+
self.font_18_bold = Font(size=18, bold=True)
|
|
225
228
|
self.font_20_bold = Font(size=20, bold=True)
|
|
226
229
|
|
|
227
230
|
self.request = request
|
|
@@ -263,6 +266,7 @@ class CanteenWorkBook:
|
|
|
263
266
|
|
|
264
267
|
def fill_in_non_storage_sheet(self):
|
|
265
268
|
sheet = self.non_storage_sheet
|
|
269
|
+
sheet.sheet_properties.tabColor = "e616ff"
|
|
266
270
|
user = self.user
|
|
267
271
|
title_cell = sheet.cell(1, 1)
|
|
268
272
|
title_cell.value = _(
|
|
@@ -367,7 +371,7 @@ class CanteenWorkBook:
|
|
|
367
371
|
"Total Price Text: {total_price_text} {total_price}"
|
|
368
372
|
).format(
|
|
369
373
|
total_price_text=get_CNY_TEXT(summary_total_price),
|
|
370
|
-
total_price=summary_total_price,
|
|
374
|
+
total_price=summary_total_price.normalize(),
|
|
371
375
|
)
|
|
372
376
|
if self.is_zh_CN
|
|
373
377
|
else _(
|
|
@@ -383,7 +387,9 @@ class CanteenWorkBook:
|
|
|
383
387
|
handler_row_num = summary_row_num + 1
|
|
384
388
|
handler_cell = sheet.cell(handler_row_num, 1)
|
|
385
389
|
handler_cell.border = self.thin_border
|
|
386
|
-
handler_cell.value = _("Handler:")
|
|
390
|
+
handler_cell.value = _("Handler: {handler}").format(
|
|
391
|
+
handler=user.username
|
|
392
|
+
)
|
|
387
393
|
sheet.merge_cells(f"A{handler_row_num}:C{handler_row_num}")
|
|
388
394
|
set_row_height_in_inches(sheet, handler_row_num, 0.32)
|
|
389
395
|
|
|
@@ -430,6 +436,7 @@ class CanteenWorkBook:
|
|
|
430
436
|
|
|
431
437
|
def fill_in_consumption_sheet(self):
|
|
432
438
|
sheet = self.consumption_sheet
|
|
439
|
+
sheet.sheet_properties.tabColor = "ff8116"
|
|
433
440
|
user = self.user
|
|
434
441
|
title_cell = sheet.cell(1, 1)
|
|
435
442
|
title_cell.value = _(
|
|
@@ -509,13 +516,19 @@ class CanteenWorkBook:
|
|
|
509
516
|
)
|
|
510
517
|
)
|
|
511
518
|
& Q(meal_type=self.meal_type)
|
|
519
|
+
& Q(category__is_disabled=False)
|
|
512
520
|
& Q(is_disabled=False)
|
|
513
521
|
& Q(is_ignorable=False)
|
|
514
522
|
).distinct()
|
|
523
|
+
|
|
515
524
|
total_price_cell = sheet.cell(row_num, 2)
|
|
516
525
|
total_price_consumed = Decimal("0.0")
|
|
517
526
|
for i in ingredients:
|
|
518
|
-
consumptions = i.consumptions.filter(
|
|
527
|
+
consumptions = i.consumptions.filter(
|
|
528
|
+
Q(is_disabled=False)
|
|
529
|
+
& Q(date_of_using__lte=self.date_end)
|
|
530
|
+
& Q(date_of_using__gte=self.date_start)
|
|
531
|
+
).all()
|
|
519
532
|
total_price_consumed += sum(
|
|
520
533
|
[c.amount_used * i.unit_price for c in consumptions]
|
|
521
534
|
)
|
|
@@ -540,12 +553,16 @@ class CanteenWorkBook:
|
|
|
540
553
|
& Q(category__is_disabled=False)
|
|
541
554
|
& Q(is_disabled=False)
|
|
542
555
|
& Q(is_ignorable=False)
|
|
543
|
-
).
|
|
556
|
+
).distinct()
|
|
544
557
|
|
|
545
558
|
summary_row_num = len(categories) + header_row_num + 1
|
|
546
559
|
summary_total_price = Decimal("0.0")
|
|
547
560
|
for i in ingredients:
|
|
548
|
-
consumptions = i.consumptions.filter(
|
|
561
|
+
consumptions = i.consumptions.filter(
|
|
562
|
+
Q(is_disabled=False)
|
|
563
|
+
& Q(date_of_using__lte=self.date_end)
|
|
564
|
+
& Q(date_of_using__gte=self.date_start)
|
|
565
|
+
).all()
|
|
549
566
|
summary_total_price += sum(
|
|
550
567
|
[c.amount_used * i.unit_price for c in consumptions]
|
|
551
568
|
)
|
|
@@ -556,14 +573,14 @@ class CanteenWorkBook:
|
|
|
556
573
|
"Total Price Text: {total_price_text} {total_price}"
|
|
557
574
|
).format(
|
|
558
575
|
total_price_text=get_CNY_TEXT(summary_total_price),
|
|
559
|
-
total_price=summary_total_price,
|
|
576
|
+
total_price=summary_total_price.normalize(),
|
|
560
577
|
)
|
|
561
578
|
if self.is_zh_CN
|
|
562
579
|
else _(
|
|
563
580
|
"Total Price Text: {total_price_text} {total_price}"
|
|
564
581
|
).format(
|
|
565
582
|
total_price_text=str(summary_total_price),
|
|
566
|
-
total_price=summary_total_price,
|
|
583
|
+
total_price=summary_total_price.normalize(),
|
|
567
584
|
)
|
|
568
585
|
)
|
|
569
586
|
sheet.merge_cells(f"A{summary_row_num}:C{summary_row_num}")
|
|
@@ -572,7 +589,9 @@ class CanteenWorkBook:
|
|
|
572
589
|
handler_row_num = summary_row_num + 1
|
|
573
590
|
handler_cell = sheet.cell(handler_row_num, 1)
|
|
574
591
|
handler_cell.border = self.thin_border
|
|
575
|
-
handler_cell.value = _("Handler:")
|
|
592
|
+
handler_cell.value = _("Handler: {handler}").format(
|
|
593
|
+
handler=user.username
|
|
594
|
+
)
|
|
576
595
|
sheet.merge_cells(f"A{handler_row_num}:C{handler_row_num}")
|
|
577
596
|
set_row_height_in_inches(sheet, handler_row_num, 0.32)
|
|
578
597
|
|
|
@@ -619,6 +638,7 @@ class CanteenWorkBook:
|
|
|
619
638
|
|
|
620
639
|
def fill_in_storage_sheet(self):
|
|
621
640
|
sheet = self.storage_sheet
|
|
641
|
+
sheet.sheet_properties.tabColor = "16d2ff"
|
|
622
642
|
user = self.user
|
|
623
643
|
title_cell = sheet.cell(1, 1)
|
|
624
644
|
title_cell.value = _(
|
|
@@ -723,7 +743,7 @@ class CanteenWorkBook:
|
|
|
723
743
|
"Total Price Text: {total_price_text} {total_price}"
|
|
724
744
|
).format(
|
|
725
745
|
total_price_text=get_CNY_TEXT(summary_total_price),
|
|
726
|
-
total_price=summary_total_price,
|
|
746
|
+
total_price=summary_total_price.normalize(),
|
|
727
747
|
)
|
|
728
748
|
if self.is_zh_CN
|
|
729
749
|
else _(
|
|
@@ -739,7 +759,9 @@ class CanteenWorkBook:
|
|
|
739
759
|
handler_row_num = summary_row_num + 1
|
|
740
760
|
handler_cell = sheet.cell(handler_row_num, 1)
|
|
741
761
|
handler_cell.border = self.thin_border
|
|
742
|
-
handler_cell.value = _("Handler:")
|
|
762
|
+
handler_cell.value = _("Handler: {handler}").format(
|
|
763
|
+
handler=user.username
|
|
764
|
+
)
|
|
743
765
|
sheet.merge_cells(f"A{handler_row_num}:C{handler_row_num}")
|
|
744
766
|
set_row_height_in_inches(sheet, handler_row_num, 0.32)
|
|
745
767
|
|
|
@@ -786,6 +808,7 @@ class CanteenWorkBook:
|
|
|
786
808
|
|
|
787
809
|
def fill_in_consumption_list_sheet(self):
|
|
788
810
|
sheet = self.consumption_list_sheet
|
|
811
|
+
sheet.sheet_properties.tabColor = "ff9e16"
|
|
789
812
|
user = self.user
|
|
790
813
|
consumption_rows_count = 21
|
|
791
814
|
categories = Category.objects.filter(
|
|
@@ -1178,6 +1201,7 @@ class CanteenWorkBook:
|
|
|
1178
1201
|
|
|
1179
1202
|
def fill_in_storage_list_sheet(self):
|
|
1180
1203
|
sheet = self.storage_list_sheet
|
|
1204
|
+
sheet.sheet_properties.tabColor = "16b1ff"
|
|
1181
1205
|
user = self.user
|
|
1182
1206
|
ingredient_rows_count = 21
|
|
1183
1207
|
ingredients = Ingredient.objects.filter(
|
|
@@ -1479,7 +1503,7 @@ class CanteenWorkBook:
|
|
|
1479
1503
|
signature_row_num = summary_row_num + 1
|
|
1480
1504
|
signature_cell = sheet.cell(signature_row_num, 1)
|
|
1481
1505
|
signature_cell.value = _(
|
|
1482
|
-
" Reviewer: Handler:{handler} Weigher: Warehouseman: "
|
|
1506
|
+
" Reviewer: Handler: {handler} Weigher: Warehouseman: "
|
|
1483
1507
|
).format(handler=user.username)
|
|
1484
1508
|
signature_cell.font = self.font_14
|
|
1485
1509
|
signature_cell.alignment = self.center_alignment
|
|
@@ -1500,6 +1524,7 @@ class CanteenWorkBook:
|
|
|
1500
1524
|
|
|
1501
1525
|
def fill_in_cover_sheet(self):
|
|
1502
1526
|
sheet = self.cover_sheet
|
|
1527
|
+
sheet.sheet_properties.tabColor = "9416ff"
|
|
1503
1528
|
user = self.user
|
|
1504
1529
|
title_cell = sheet.cell(1, 1)
|
|
1505
1530
|
title_cell.value = _(
|
|
@@ -1615,6 +1640,7 @@ class CanteenWorkBook:
|
|
|
1615
1640
|
|
|
1616
1641
|
def fill_in_surplus_sheet(self):
|
|
1617
1642
|
sheet = self.surplus_sheet
|
|
1643
|
+
sheet.sheet_properties.tabColor = "29ff16"
|
|
1618
1644
|
user = self.user
|
|
1619
1645
|
ingredient_rows_count = 17
|
|
1620
1646
|
|
|
@@ -1923,7 +1949,7 @@ class CanteenWorkBook:
|
|
|
1923
1949
|
signature_row_num,
|
|
1924
1950
|
1,
|
|
1925
1951
|
_(
|
|
1926
|
-
" Reviewer: Handler:{handler_name} Weigher: Warehouseman: "
|
|
1952
|
+
" Reviewer: Handler: {handler_name} Weigher: Warehouseman: "
|
|
1927
1953
|
).format(handler_name=user.username),
|
|
1928
1954
|
)
|
|
1929
1955
|
sheet.merge_cells(f"A{signature_row_num}:I{signature_row_num}")
|
|
@@ -1943,6 +1969,7 @@ class CanteenWorkBook:
|
|
|
1943
1969
|
|
|
1944
1970
|
def fill_in_non_storage_list_sheet(self):
|
|
1945
1971
|
sheet = self.non_storage_list_sheet
|
|
1972
|
+
sheet.sheet_properties.tabColor = "ff16ee"
|
|
1946
1973
|
user = self.user
|
|
1947
1974
|
ingredient_rows_count = 11
|
|
1948
1975
|
|
|
@@ -2137,16 +2164,512 @@ class CanteenWorkBook:
|
|
|
2137
2164
|
|
|
2138
2165
|
def fill_in_food_sheets(self):
|
|
2139
2166
|
user = self.request.user
|
|
2140
|
-
|
|
2141
|
-
|
|
2167
|
+
wb = self.wb
|
|
2168
|
+
year = datetime.now().year
|
|
2169
|
+
date_start = date(year, 1, 1)
|
|
2170
|
+
date_end = date(year, 12, 31)
|
|
2142
2171
|
meal_type = self.meal_type
|
|
2143
2172
|
|
|
2144
|
-
ingredients =
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2173
|
+
ingredients = (
|
|
2174
|
+
Ingredient.objects.filter(
|
|
2175
|
+
Q(is_disabled=False)
|
|
2176
|
+
& Q(is_ignorable=False)
|
|
2177
|
+
& Q(user=user)
|
|
2178
|
+
& Q(meal_type=meal_type)
|
|
2179
|
+
)
|
|
2180
|
+
.prefetch_related("consumptions")
|
|
2181
|
+
.all()
|
|
2182
|
+
)
|
|
2183
|
+
ingredients = [
|
|
2184
|
+
i
|
|
2185
|
+
for i in ingredients
|
|
2186
|
+
if date_start <= i.storage_date <= date_end
|
|
2187
|
+
or any(
|
|
2188
|
+
[
|
|
2189
|
+
date_start <= c.date_of_using <= date_end
|
|
2190
|
+
for c in i.consumptions.all()
|
|
2191
|
+
if c.is_disabled == False
|
|
2192
|
+
]
|
|
2193
|
+
)
|
|
2194
|
+
]
|
|
2195
|
+
|
|
2196
|
+
ingredient_names = list(set([i.name for i in ingredients]))
|
|
2197
|
+
for ingredient_name_index, ingredient_name in enumerate(
|
|
2198
|
+
ingredient_names
|
|
2199
|
+
):
|
|
2200
|
+
sheet = wb.create_sheet(ingredient_name)
|
|
2201
|
+
sheet.sheet_properties.tabColor = "1689ff"
|
|
2202
|
+
named_ingredients = [
|
|
2203
|
+
i for i in ingredients if i.name == ingredient_name
|
|
2204
|
+
]
|
|
2205
|
+
year_ingredient0 = named_ingredients[0]
|
|
2206
|
+
|
|
2207
|
+
year_storage_quantity = Decimal("0")
|
|
2208
|
+
year_storage_total_price = Decimal("0.0")
|
|
2209
|
+
year_consumption_quantity = Decimal("0")
|
|
2210
|
+
year_consumption_total_price = Decimal("0.0")
|
|
2211
|
+
ingredient_rows_count = 31
|
|
2212
|
+
|
|
2213
|
+
for col_index, col_width in [
|
|
2214
|
+
[1, 0.4],
|
|
2215
|
+
[2, 0.4],
|
|
2216
|
+
[3, 1.86],
|
|
2217
|
+
[4, 0.7],
|
|
2218
|
+
[5, 0.8],
|
|
2219
|
+
[6, 0.95],
|
|
2220
|
+
[7, 0.7],
|
|
2221
|
+
[8, 0.8],
|
|
2222
|
+
[9, 0.97],
|
|
2223
|
+
[10, 0.7],
|
|
2224
|
+
[11, 0.8],
|
|
2225
|
+
[12, 0.8],
|
|
2226
|
+
[13, 1.67],
|
|
2227
|
+
]:
|
|
2228
|
+
set_column_width_in_inches(sheet, col_index, col_width)
|
|
2229
|
+
|
|
2230
|
+
for month_index in range(12):
|
|
2231
|
+
month = month_index + 1
|
|
2232
|
+
|
|
2233
|
+
___, month_days = calendar.monthrange(year, month)
|
|
2234
|
+
month_day_1 = date(year, month, 1)
|
|
2235
|
+
month_day_n1 = date(year, month, month_days)
|
|
2236
|
+
|
|
2237
|
+
row_num = (ingredient_rows_count + 8) * month_index
|
|
2238
|
+
title_row_num = row_num + 1
|
|
2239
|
+
title_cell = sheet.cell(title_row_num, 1)
|
|
2240
|
+
title_cell.value = (
|
|
2241
|
+
_(
|
|
2242
|
+
"Ingredients Storage and Consumption Records of Principal Canteen"
|
|
2243
|
+
)
|
|
2244
|
+
if self.is_school
|
|
2245
|
+
else _(
|
|
2246
|
+
"Ingredients Storage and Consumption Records of Affiliation Canteen"
|
|
2247
|
+
)
|
|
2248
|
+
)
|
|
2249
|
+
title_cell.font = self.font_18_bold
|
|
2250
|
+
title_cell.alignment = self.center_alignment
|
|
2251
|
+
set_row_height_in_inches(sheet, title_row_num, 0.38)
|
|
2252
|
+
sheet.merge_cells(f"A{title_row_num}:M{title_row_num}")
|
|
2253
|
+
|
|
2254
|
+
ingredient_name_row_num = title_row_num + 1
|
|
2255
|
+
|
|
2256
|
+
for row_index in range(
|
|
2257
|
+
ingredient_name_row_num, ingredient_rows_count + 6 + 1
|
|
2258
|
+
):
|
|
2259
|
+
set_row_height_in_inches(sheet, row_index, 0.22)
|
|
2260
|
+
|
|
2261
|
+
ingredient_name_cell = sheet.cell(ingredient_name_row_num, 1)
|
|
2262
|
+
ingredient_name_cell.value = _(
|
|
2263
|
+
"Ingredient Name: {ingredient_name} ({quantity_unit_name})"
|
|
2264
|
+
).format(
|
|
2265
|
+
ingredient_name=ingredient_name,
|
|
2266
|
+
quantity_unit_name=year_ingredient0.quantity_unit_name,
|
|
2267
|
+
)
|
|
2268
|
+
ingredient_name_cell.alignment = self.left_alignment
|
|
2269
|
+
ingredient_name_cell.font = self.font_14
|
|
2270
|
+
sheet.merge_cells(
|
|
2271
|
+
f"A{ingredient_name_row_num}:M{ingredient_name_row_num}"
|
|
2272
|
+
)
|
|
2273
|
+
|
|
2274
|
+
year_header_row_num = ingredient_name_row_num + 1
|
|
2275
|
+
|
|
2276
|
+
for row_index in range(
|
|
2277
|
+
year_header_row_num, year_header_row_num + 1 + 1
|
|
2278
|
+
):
|
|
2279
|
+
for col_index in range(1, 14):
|
|
2280
|
+
sheet.cell(row_index, col_index).border = (
|
|
2281
|
+
self.thin_border
|
|
2282
|
+
)
|
|
2283
|
+
|
|
2284
|
+
year_header_cell = sheet.cell(year_header_row_num, 1)
|
|
2285
|
+
year_header_cell.value = _("Year {year}").format(year=year)
|
|
2286
|
+
year_header_cell.font = self.font_14
|
|
2287
|
+
year_header_cell.alignment = self.center_alignment
|
|
2288
|
+
year_header_cell.border = self.thin_border
|
|
2289
|
+
sheet.merge_cells(
|
|
2290
|
+
f"A{year_header_row_num}:B{year_header_row_num}"
|
|
2291
|
+
)
|
|
2292
|
+
|
|
2293
|
+
storage_header_row_num = year_header_row_num
|
|
2294
|
+
storage_header_cell = sheet.cell(storage_header_row_num, 4)
|
|
2295
|
+
storage_header_cell.value = _("Storage (Food Sheet)")
|
|
2296
|
+
storage_header_cell.font = self.font_14
|
|
2297
|
+
storage_header_cell.alignment = self.center_alignment
|
|
2298
|
+
storage_header_cell.border = self.thin_border
|
|
2299
|
+
sheet.merge_cells(
|
|
2300
|
+
f"D{storage_header_row_num}:F{storage_header_row_num}"
|
|
2301
|
+
)
|
|
2302
|
+
|
|
2303
|
+
consumption_header_row_num = year_header_row_num
|
|
2304
|
+
consumption_header_cell = sheet.cell(
|
|
2305
|
+
consumption_header_row_num, 7
|
|
2306
|
+
)
|
|
2307
|
+
consumption_header_cell.value = _("Consumption (Food Sheet)")
|
|
2308
|
+
consumption_header_cell.font = self.font_14
|
|
2309
|
+
consumption_header_cell.alignment = self.center_alignment
|
|
2310
|
+
consumption_header_cell.border = self.thin_border
|
|
2311
|
+
sheet.merge_cells(
|
|
2312
|
+
f"G{consumption_header_row_num}:I{consumption_header_row_num}"
|
|
2313
|
+
)
|
|
2314
|
+
|
|
2315
|
+
surplus_header_row_num = year_header_row_num
|
|
2316
|
+
surplus_header_cell = sheet.cell(surplus_header_row_num, 10)
|
|
2317
|
+
surplus_header_cell.value = _("Surplus (Food Sheet)")
|
|
2318
|
+
surplus_header_cell.font = self.font_14
|
|
2319
|
+
surplus_header_cell.alignment = self.center_alignment
|
|
2320
|
+
surplus_header_cell.border = self.thin_border
|
|
2321
|
+
sheet.merge_cells(
|
|
2322
|
+
f"J{surplus_header_row_num}:L{surplus_header_row_num}"
|
|
2323
|
+
)
|
|
2324
|
+
|
|
2325
|
+
num_header_row_num = year_header_row_num
|
|
2326
|
+
num_header_cell = sheet.cell(num_header_row_num, 13)
|
|
2327
|
+
num_header_cell.value = _(
|
|
2328
|
+
"Storage/Consumption No. (Food Sheet)"
|
|
2329
|
+
)
|
|
2330
|
+
num_header_cell.font = self.font_14
|
|
2331
|
+
num_header_cell.alignment = self.center_alignment
|
|
2332
|
+
num_header_cell.border = self.thin_border
|
|
2333
|
+
sheet.merge_cells(
|
|
2334
|
+
f"M{num_header_row_num}:M{num_header_row_num+1}"
|
|
2335
|
+
)
|
|
2336
|
+
|
|
2337
|
+
month_header_row_num = year_header_row_num + 1
|
|
2338
|
+
month_header_cell = sheet.cell(month_header_row_num, 1)
|
|
2339
|
+
month_header_cell.value = _("Month (Food Sheet)")
|
|
2340
|
+
month_header_cell.font = self.font_14
|
|
2341
|
+
month_header_cell.alignment = self.center_alignment
|
|
2342
|
+
month_header_cell.border = self.thin_border
|
|
2343
|
+
|
|
2344
|
+
day_header_row_num = year_header_row_num + 1
|
|
2345
|
+
day_header_cell = sheet.cell(day_header_row_num, 2)
|
|
2346
|
+
day_header_cell.value = _("Day (Food Sheet)")
|
|
2347
|
+
day_header_cell.font = self.font_14
|
|
2348
|
+
day_header_cell.alignment = self.center_alignment
|
|
2349
|
+
day_header_cell.border = self.thin_border
|
|
2350
|
+
|
|
2351
|
+
price_header_row_num = day_header_row_num
|
|
2352
|
+
for col_index in range(4, 13, 3):
|
|
2353
|
+
quantity_header_col_num = col_index
|
|
2354
|
+
unit_price_header_col_num = col_index + 1
|
|
2355
|
+
total_price_header_col_num = col_index + 2
|
|
2356
|
+
|
|
2357
|
+
quantity_header_cell = sheet.cell(
|
|
2358
|
+
price_header_row_num, quantity_header_col_num
|
|
2359
|
+
)
|
|
2360
|
+
quantity_header_cell.value = _("Quantity (Food Sheet)")
|
|
2361
|
+
quantity_header_cell.font = self.font_14
|
|
2362
|
+
quantity_header_cell.alignment = self.center_alignment
|
|
2363
|
+
quantity_header_cell.border = self.thin_border
|
|
2364
|
+
|
|
2365
|
+
unit_price_header_cell = sheet.cell(
|
|
2366
|
+
price_header_row_num, unit_price_header_col_num
|
|
2367
|
+
)
|
|
2368
|
+
unit_price_header_cell.value = _("Unit Price (Food Sheet)")
|
|
2369
|
+
unit_price_header_cell.font = self.font_14
|
|
2370
|
+
unit_price_header_cell.alignment = self.center_alignment
|
|
2371
|
+
unit_price_header_cell.border = self.thin_border
|
|
2372
|
+
|
|
2373
|
+
total_price_header_cell = sheet.cell(
|
|
2374
|
+
price_header_row_num, total_price_header_col_num
|
|
2375
|
+
)
|
|
2376
|
+
total_price_header_cell.value = _(
|
|
2377
|
+
"Total Price (Food Sheet)"
|
|
2378
|
+
)
|
|
2379
|
+
total_price_header_cell.font = self.font_14
|
|
2380
|
+
total_price_header_cell.alignment = self.center_alignment
|
|
2381
|
+
total_price_header_cell.border = self.thin_border
|
|
2382
|
+
|
|
2383
|
+
month_surplus_header_row_num = month_header_row_num + 1
|
|
2384
|
+
month_surplus_header_cell = sheet.cell(
|
|
2385
|
+
month_surplus_header_row_num, 3
|
|
2386
|
+
)
|
|
2387
|
+
month_surplus_header_cell.value = (
|
|
2388
|
+
_("Surplus for last month")
|
|
2389
|
+
if month > 1
|
|
2390
|
+
else _("Surplus for last year")
|
|
2391
|
+
)
|
|
2392
|
+
|
|
2393
|
+
date_day_1 = month_day_1
|
|
2394
|
+
_date_day_1 = date_day_1 + timedelta(days=-1)
|
|
2395
|
+
|
|
2396
|
+
if any(
|
|
2397
|
+
[i.storage_date < date_day_1 for i in named_ingredients]
|
|
2398
|
+
):
|
|
2399
|
+
remaining_quantity_last_month = sum(
|
|
2400
|
+
[
|
|
2401
|
+
i.get_remaining_quantity(_date_day_1)
|
|
2402
|
+
for i in named_ingredients
|
|
2403
|
+
]
|
|
2404
|
+
)
|
|
2405
|
+
remaining_total_price_last_month = sum(
|
|
2406
|
+
[
|
|
2407
|
+
i.unit_price * i.get_remaining_quantity(_date_day_1)
|
|
2408
|
+
for i in named_ingredients
|
|
2409
|
+
]
|
|
2410
|
+
)
|
|
2411
|
+
unit_price = (
|
|
2412
|
+
Decimal(str(remaining_total_price_last_month))
|
|
2413
|
+
/ Decimal(str(remaining_quantity_last_month))
|
|
2414
|
+
if remaining_quantity_last_month
|
|
2415
|
+
else Decimal("0.0")
|
|
2416
|
+
)
|
|
2417
|
+
|
|
2418
|
+
sheet.cell(
|
|
2419
|
+
month_surplus_header_row_num,
|
|
2420
|
+
4,
|
|
2421
|
+
remaining_quantity_last_month,
|
|
2422
|
+
)
|
|
2423
|
+
sheet.cell(
|
|
2424
|
+
month_surplus_header_row_num,
|
|
2425
|
+
6,
|
|
2426
|
+
remaining_total_price_last_month,
|
|
2427
|
+
)
|
|
2428
|
+
sheet.cell(
|
|
2429
|
+
month_surplus_header_row_num, 5, unit_price.normalize()
|
|
2430
|
+
)
|
|
2431
|
+
|
|
2432
|
+
month_ingredients = []
|
|
2433
|
+
storage_dates = list(
|
|
2434
|
+
set(
|
|
2435
|
+
[
|
|
2436
|
+
i.storage_date
|
|
2437
|
+
for i in ingredients
|
|
2438
|
+
if month_day_1 <= i.storage_date <= month_day_n1
|
|
2439
|
+
]
|
|
2440
|
+
)
|
|
2441
|
+
)
|
|
2442
|
+
consumption_dates = []
|
|
2443
|
+
for i in ingredients:
|
|
2444
|
+
consumptions = [
|
|
2445
|
+
c for c in i.consumptions.all() if not c.is_disabled
|
|
2446
|
+
]
|
|
2447
|
+
for c in consumptions:
|
|
2448
|
+
if (
|
|
2449
|
+
month_day_1 <= c.date_of_using <= month_day_n1
|
|
2450
|
+
and not c.date_of_using in consumption_dates
|
|
2451
|
+
):
|
|
2452
|
+
consumption_dates.append(c.date_of_using)
|
|
2453
|
+
|
|
2454
|
+
storage_dates = sorted(storage_dates)
|
|
2455
|
+
consumption_dates = sorted(consumption_dates)
|
|
2456
|
+
|
|
2457
|
+
for ingredient in named_ingredients:
|
|
2458
|
+
consumptions = [
|
|
2459
|
+
c
|
|
2460
|
+
for c in ingredient.consumptions.all()
|
|
2461
|
+
if not c.is_disabled
|
|
2462
|
+
]
|
|
2463
|
+
ingredient_consumption_dates = [
|
|
2464
|
+
c.date_of_using for c in consumptions
|
|
2465
|
+
]
|
|
2466
|
+
if month_day_1 <= ingredient.storage_date <= month_day_n1:
|
|
2467
|
+
month_ingredients.append(ingredient)
|
|
2468
|
+
elif any(
|
|
2469
|
+
[
|
|
2470
|
+
month_day_1 <= consumption_date <= month_day_n1
|
|
2471
|
+
for consumption_date in ingredient_consumption_dates
|
|
2472
|
+
]
|
|
2473
|
+
):
|
|
2474
|
+
month_ingredients.append(ingredient)
|
|
2475
|
+
|
|
2476
|
+
month_storage_quantity = Decimal("0")
|
|
2477
|
+
month_storage_total_price = Decimal("0.0")
|
|
2478
|
+
month_consumption_quantity = Decimal("0")
|
|
2479
|
+
month_consumption_total_price = Decimal("0.0")
|
|
2480
|
+
|
|
2481
|
+
for day_index in range(ingredient_rows_count):
|
|
2482
|
+
|
|
2483
|
+
if day_index + 1 <= month_days:
|
|
2484
|
+
day = date(year, month, day_index + 1)
|
|
2485
|
+
ingredient_row_num = (
|
|
2486
|
+
month_surplus_header_row_num + 1 + day_index
|
|
2487
|
+
)
|
|
2488
|
+
sheet.cell(ingredient_row_num, 1, day.month)
|
|
2489
|
+
sheet.cell(ingredient_row_num, 2, day.day)
|
|
2490
|
+
storage_quantity = sum(
|
|
2491
|
+
[
|
|
2492
|
+
i.quantity
|
|
2493
|
+
for i in month_ingredients
|
|
2494
|
+
if i.storage_date == day
|
|
2495
|
+
]
|
|
2496
|
+
)
|
|
2497
|
+
storage_total_price = sum(
|
|
2498
|
+
[
|
|
2499
|
+
i.total_price
|
|
2500
|
+
for i in month_ingredients
|
|
2501
|
+
if i.storage_date == day
|
|
2502
|
+
]
|
|
2503
|
+
)
|
|
2504
|
+
storage_unit_price = (
|
|
2505
|
+
Decimal(str(storage_total_price))
|
|
2506
|
+
/ Decimal(str(storage_quantity))
|
|
2507
|
+
if storage_quantity
|
|
2508
|
+
else Decimal("0.0")
|
|
2509
|
+
)
|
|
2510
|
+
storage_unit_price = storage_unit_price.normalize()
|
|
2511
|
+
if storage_quantity:
|
|
2512
|
+
sheet.cell(ingredient_row_num, 4, storage_quantity)
|
|
2513
|
+
sheet.cell(
|
|
2514
|
+
ingredient_row_num, 5, storage_unit_price
|
|
2515
|
+
)
|
|
2516
|
+
sheet.cell(
|
|
2517
|
+
ingredient_row_num, 6, storage_total_price
|
|
2518
|
+
)
|
|
2519
|
+
|
|
2520
|
+
consumption_quantity = Decimal("0")
|
|
2521
|
+
consumption_total_price = Decimal("0.0")
|
|
2522
|
+
|
|
2523
|
+
for i in month_ingredients:
|
|
2524
|
+
for c in [
|
|
2525
|
+
c
|
|
2526
|
+
for c in i.consumptions.all()
|
|
2527
|
+
if not c.is_disabled
|
|
2528
|
+
]:
|
|
2529
|
+
if c.date_of_using == day:
|
|
2530
|
+
consumption_quantity += c.amount_used
|
|
2531
|
+
consumption_total_price += (
|
|
2532
|
+
c.amount_used * i.unit_price
|
|
2533
|
+
)
|
|
2534
|
+
|
|
2535
|
+
consumption_unit_price = (
|
|
2536
|
+
(consumption_total_price / consumption_quantity)
|
|
2537
|
+
if consumption_quantity
|
|
2538
|
+
else Decimal("0.0")
|
|
2539
|
+
)
|
|
2540
|
+
consumption_unit_price = (
|
|
2541
|
+
f"{consumption_unit_price:.{decimal_prec}f}"
|
|
2542
|
+
)
|
|
2543
|
+
|
|
2544
|
+
if consumption_quantity:
|
|
2545
|
+
sheet.cell(
|
|
2546
|
+
ingredient_row_num, 7, consumption_quantity
|
|
2547
|
+
)
|
|
2548
|
+
sheet.cell(
|
|
2549
|
+
ingredient_row_num, 8, consumption_unit_price
|
|
2550
|
+
)
|
|
2551
|
+
sheet.cell(
|
|
2552
|
+
ingredient_row_num, 9, consumption_total_price
|
|
2553
|
+
)
|
|
2554
|
+
|
|
2555
|
+
surplus_quantity = Decimal("0")
|
|
2556
|
+
surplus_total_price = Decimal("0.0")
|
|
2557
|
+
for i in month_ingredients:
|
|
2558
|
+
if i.storage_date > day:
|
|
2559
|
+
continue
|
|
2560
|
+
remaining_quantity = i.get_remaining_quantity(day)
|
|
2561
|
+
surplus_quantity += remaining_quantity
|
|
2562
|
+
surplus_total_price += (
|
|
2563
|
+
remaining_quantity * i.unit_price
|
|
2564
|
+
)
|
|
2565
|
+
surplus_unit_price = (
|
|
2566
|
+
(surplus_total_price / surplus_quantity)
|
|
2567
|
+
if surplus_quantity
|
|
2568
|
+
else Decimal("0.0")
|
|
2569
|
+
)
|
|
2570
|
+
surplus_unit_price = (
|
|
2571
|
+
f"{surplus_unit_price:.{decimal_prec}f}"
|
|
2572
|
+
)
|
|
2573
|
+
|
|
2574
|
+
if surplus_quantity:
|
|
2575
|
+
sheet.cell(ingredient_row_num, 10, surplus_quantity)
|
|
2576
|
+
sheet.cell(
|
|
2577
|
+
ingredient_row_num, 11, surplus_unit_price
|
|
2578
|
+
)
|
|
2579
|
+
sheet.cell(
|
|
2580
|
+
ingredient_row_num, 12, surplus_total_price
|
|
2581
|
+
)
|
|
2582
|
+
elif consumption_quantity:
|
|
2583
|
+
sheet.cell(ingredient_row_num, 10, "0")
|
|
2584
|
+
sheet.cell(ingredient_row_num, 11, "")
|
|
2585
|
+
sheet.cell(ingredient_row_num, 12, "0")
|
|
2586
|
+
|
|
2587
|
+
num_value = ""
|
|
2588
|
+
if storage_quantity:
|
|
2589
|
+
storage_num = storage_dates.index(day) + 1
|
|
2590
|
+
num_value += (
|
|
2591
|
+
(f"R{month:0>2}{storage_num:0>2}")
|
|
2592
|
+
if self.is_zh_CN
|
|
2593
|
+
else (f"S{month:0>2}{storage_num:0>2}")
|
|
2594
|
+
)
|
|
2595
|
+
|
|
2596
|
+
if consumption_quantity:
|
|
2597
|
+
if not num_value == "":
|
|
2598
|
+
num_value += _("and (Food Sheet)")
|
|
2599
|
+
consumption_num = consumption_dates.index(day) + 1
|
|
2600
|
+
num_value += (
|
|
2601
|
+
(f"C{month:0>2}{consumption_num:0>2}")
|
|
2602
|
+
if self.is_zh_CN
|
|
2603
|
+
else (f"C{month:0>2}{consumption_num:0>2}")
|
|
2604
|
+
)
|
|
2605
|
+
|
|
2606
|
+
sheet.cell(ingredient_row_num, 13, num_value)
|
|
2607
|
+
|
|
2608
|
+
month_storage_quantity += storage_quantity
|
|
2609
|
+
month_storage_total_price += storage_total_price
|
|
2610
|
+
month_consumption_quantity += consumption_quantity
|
|
2611
|
+
month_consumption_total_price += consumption_total_price
|
|
2612
|
+
|
|
2613
|
+
year_storage_quantity += storage_quantity
|
|
2614
|
+
year_storage_total_price += storage_total_price
|
|
2615
|
+
year_consumption_quantity += consumption_quantity
|
|
2616
|
+
year_consumption_total_price += consumption_total_price
|
|
2617
|
+
|
|
2618
|
+
for row_index in range(
|
|
2619
|
+
month_surplus_header_row_num,
|
|
2620
|
+
month_surplus_header_row_num
|
|
2621
|
+
+ ingredient_rows_count
|
|
2622
|
+
+ 2
|
|
2623
|
+
+ 1,
|
|
2624
|
+
):
|
|
2625
|
+
for col_index in range(1, 13 + 1):
|
|
2626
|
+
cell = sheet.cell(row_index, col_index)
|
|
2627
|
+
cell.font = self.font_12
|
|
2628
|
+
cell.alignment = self.center_alignment
|
|
2629
|
+
cell.border = self.thin_border
|
|
2630
|
+
|
|
2631
|
+
month_summary_row_num = (
|
|
2632
|
+
year_header_row_num + 2 + ingredient_rows_count + 1
|
|
2633
|
+
)
|
|
2634
|
+
year_accumulation_row_num = month_summary_row_num + 1
|
|
2635
|
+
|
|
2636
|
+
sheet.cell(month_summary_row_num, 3, _("Monthly Summary"))
|
|
2637
|
+
sheet.cell(month_summary_row_num, 4, month_storage_quantity)
|
|
2638
|
+
sheet.cell(month_summary_row_num, 6, month_storage_total_price)
|
|
2639
|
+
sheet.cell(month_summary_row_num, 7, month_consumption_quantity)
|
|
2640
|
+
sheet.cell(
|
|
2641
|
+
month_summary_row_num, 9, month_consumption_total_price
|
|
2642
|
+
)
|
|
2643
|
+
|
|
2644
|
+
sheet.cell(year_accumulation_row_num, 3, _("Year Accumulation"))
|
|
2645
|
+
sheet.cell(year_accumulation_row_num, 4, year_storage_quantity)
|
|
2646
|
+
sheet.cell(
|
|
2647
|
+
year_accumulation_row_num, 6, year_storage_total_price
|
|
2648
|
+
)
|
|
2649
|
+
sheet.cell(
|
|
2650
|
+
year_accumulation_row_num, 7, year_consumption_quantity
|
|
2651
|
+
)
|
|
2652
|
+
sheet.cell(
|
|
2653
|
+
year_accumulation_row_num,
|
|
2654
|
+
9,
|
|
2655
|
+
year_consumption_total_price,
|
|
2656
|
+
)
|
|
2657
|
+
|
|
2658
|
+
note_row_num = year_accumulation_row_num + 1
|
|
2659
|
+
sheet.cell(
|
|
2660
|
+
note_row_num,
|
|
2661
|
+
2,
|
|
2662
|
+
(
|
|
2663
|
+
_(
|
|
2664
|
+
"Note: The 'Principal Canteen Material Storage and Outbound Ledger' is registered on a daily basis based on the storage and outbound receipts."
|
|
2665
|
+
)
|
|
2666
|
+
if self.is_school
|
|
2667
|
+
else _(
|
|
2668
|
+
"Note: The 'Affiliation Canteen Material Storage and Outbound Ledger' is registered on a daily basis based on the storage and outbound receipts."
|
|
2669
|
+
)
|
|
2670
|
+
),
|
|
2671
|
+
)
|
|
2672
|
+
sheet.merge_cells(f"B{note_row_num}:M{note_row_num}")
|
|
2150
2673
|
|
|
2151
2674
|
def fill_in(self):
|
|
2152
2675
|
self.fill_in_cover_sheet()
|
|
@@ -2157,7 +2680,7 @@ class CanteenWorkBook:
|
|
|
2157
2680
|
self.fill_in_consumption_sheet()
|
|
2158
2681
|
self.fill_in_consumption_list_sheet()
|
|
2159
2682
|
self.fill_in_surplus_sheet()
|
|
2160
|
-
|
|
2683
|
+
self.fill_in_food_sheets()
|
|
2161
2684
|
|
|
2162
2685
|
return self.wb
|
|
2163
2686
|
|