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.

Files changed (34) hide show
  1. fnschoo1/__init__.py +1 -1
  2. fnschoo1/canteen/models.py +4 -0
  3. fnschoo1/canteen/templates/canteen/category/create.html +3 -1
  4. fnschoo1/canteen/templates/canteen/category/delete.html +3 -1
  5. fnschoo1/canteen/templates/canteen/category/update.html +3 -1
  6. fnschoo1/canteen/templates/canteen/consumption/create.html +31 -30
  7. fnschoo1/canteen/templates/canteen/ingredient/create.html +6 -2
  8. fnschoo1/canteen/templates/canteen/ingredient/create_one.html +3 -1
  9. fnschoo1/canteen/templates/canteen/ingredient/delete.html +3 -1
  10. fnschoo1/canteen/templates/canteen/ingredient/list.html +3 -1
  11. fnschoo1/canteen/templates/canteen/ingredient/update.html +3 -1
  12. fnschoo1/canteen/templates/canteen/meal_type/create.html +3 -1
  13. fnschoo1/canteen/templates/canteen/meal_type/delete.html +3 -1
  14. fnschoo1/canteen/templates/canteen/meal_type/update.html +3 -1
  15. fnschoo1/canteen/views.py +11 -2
  16. fnschoo1/canteen/workbook/generate.py +545 -22
  17. fnschoo1/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  18. fnschoo1/profiles/templates/profiles/create.html +3 -1
  19. fnschoo1/profiles/templates/profiles/detail.html +3 -1
  20. fnschoo1/profiles/templates/profiles/edit.html +3 -1
  21. fnschoo1/profiles/templates/profiles/log_in.html +3 -1
  22. fnschoo1/templates/includes/_footer.html +12 -4
  23. fnschoo1/templates/includes/_paginator.html +3 -1
  24. {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/METADATA +1 -1
  25. {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/RECORD +34 -34
  26. {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/SOURCES.txt.py +0 -0
  27. {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/WHEEL +0 -0
  28. {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/dependency_links.txt.py +0 -0
  29. {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/entry_points.txt +0 -0
  30. {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/entry_points.txt.py +0 -0
  31. {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/licenses/LICENSE +0 -0
  32. {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/requires.txt.py +0 -0
  33. {fnschool-20251016.81833.820.dist-info → fnschool-20251018.80328.837.dist-info}/top_level.txt +0 -0
  34. {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(is_disabled=False).all()
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
- ).all()
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(Q(is_disabled=False)).all()
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
- date_start = self.date_start
2141
- date_end = self.date_end
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 = Ingredient.objects.filter(
2145
- Q(is_disabled=False)
2146
- & Q(is_ignorable=False)
2147
- & Q(user=user)
2148
- & Q(meal_type=meal_type)
2149
- ).all()
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
- # self.fill_in_food_sheets()
2683
+ self.fill_in_food_sheets()
2161
2684
 
2162
2685
  return self.wb
2163
2686