fnschool 20250109.80531.837__py3-none-any.whl → 20251011.81638.854__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 (278) hide show
  1. fnschoo1/__init__.py +53 -0
  2. fnschoo1/canteen/admin.py +3 -0
  3. fnschoo1/canteen/apps.py +6 -0
  4. fnschoo1/canteen/forms.py +84 -0
  5. fnschoo1/canteen/migrations/0001_initial.py +119 -0
  6. fnschoo1/canteen/migrations/0002_ingredient_is_disabled.py +20 -0
  7. fnschoo1/canteen/migrations/0003_consumption_is_disabled_alter_ingredient_is_disabled.py +23 -0
  8. fnschoo1/canteen/migrations/0004_alter_ingredient_name_category_and_more.py +66 -0
  9. fnschoo1/canteen/migrations/0005_alter_category_created_at_alter_category_name_and_more.py +41 -0
  10. fnschoo1/canteen/migrations/0006_category_is_disabled_alter_category_user_and_more.py +49 -0
  11. fnschoo1/canteen/migrations/0007_alter_consumption_amount_used_and_more.py +30 -0
  12. fnschoo1/canteen/migrations/0008_category_abbreviation_mealtype.py +67 -0
  13. fnschoo1/canteen/migrations/0009_alter_category_abbreviation_and_more.py +55 -0
  14. fnschoo1/canteen/migrations/0010_alter_consumption_options_alter_ingredient_options_and_more.py +215 -0
  15. fnschoo1/canteen/migrations/0011_category_pin_to_consumptions_top.py +23 -0
  16. fnschoo1/canteen/migrations/0012_alter_ingredient_storage_date.py +18 -0
  17. fnschoo1/canteen/models.py +179 -0
  18. fnschoo1/canteen/templates/canteen/category/create.html +17 -0
  19. fnschoo1/canteen/templates/canteen/category/delete.html +61 -0
  20. fnschoo1/canteen/templates/canteen/category/list.html +63 -0
  21. fnschoo1/canteen/templates/canteen/category/update.html +23 -0
  22. fnschoo1/canteen/templates/canteen/close.html +11 -0
  23. fnschoo1/canteen/templates/canteen/consumption/_create.html +19 -0
  24. fnschoo1/canteen/templates/canteen/consumption/create.html +456 -0
  25. fnschoo1/canteen/templates/canteen/ingredient/close.html +11 -0
  26. fnschoo1/canteen/templates/canteen/ingredient/create.html +19 -0
  27. fnschoo1/canteen/templates/canteen/ingredient/create_one.html +17 -0
  28. fnschoo1/canteen/templates/canteen/ingredient/delete.html +41 -0
  29. fnschoo1/canteen/templates/canteen/ingredient/list.html +128 -0
  30. fnschoo1/canteen/templates/canteen/ingredient/update.html +23 -0
  31. fnschoo1/canteen/templates/canteen/meal_type/create.html +17 -0
  32. fnschoo1/canteen/templates/canteen/meal_type/delete.html +56 -0
  33. fnschoo1/canteen/templates/canteen/meal_type/list.html +59 -0
  34. fnschoo1/canteen/templates/canteen/meal_type/update.html +23 -0
  35. fnschoo1/canteen/tests.py +3 -0
  36. fnschoo1/canteen/urls.py +116 -0
  37. fnschoo1/canteen/views.py +814 -0
  38. fnschoo1/canteen/workbook/generate.py +2098 -0
  39. fnschoo1/db.sqlite3 +0 -0
  40. fnschoo1/fnschool/__init__.py +13 -0
  41. fnschoo1/fnschool/asgi.py +16 -0
  42. fnschoo1/fnschool/settings.py +167 -0
  43. fnschoo1/fnschool/templatetags/fnschool_tags.py +27 -0
  44. fnschoo1/fnschool/urls.py +30 -0
  45. fnschoo1/fnschool/views.py +9 -0
  46. fnschoo1/fnschool/wsgi.py +16 -0
  47. fnschoo1/locale/en/LC_MESSAGES/django.mo +0 -0
  48. fnschoo1/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  49. fnschoo1/manage.py +25 -0
  50. fnschoo1/profiles/admin.py +27 -0
  51. fnschoo1/profiles/apps.py +12 -0
  52. fnschoo1/profiles/forms.py +67 -0
  53. fnschoo1/profiles/migrations/0001_initial.py +192 -0
  54. fnschoo1/profiles/migrations/0002_alter_profile_bio.py +20 -0
  55. fnschoo1/profiles/migrations/0003_alter_profile_options_alter_profile_address_and_more.py +67 -0
  56. fnschoo1/profiles/migrations/0004_profile_gender.py +26 -0
  57. fnschoo1/profiles/migrations/0005_alter_profile_gender.py +23 -0
  58. fnschoo1/profiles/models.py +60 -0
  59. fnschoo1/profiles/signals.py +20 -0
  60. fnschoo1/profiles/templates/profiles/create.html +16 -0
  61. fnschoo1/profiles/templates/profiles/detail.html +14 -0
  62. fnschoo1/profiles/templates/profiles/edit.html +12 -0
  63. fnschoo1/profiles/templates/profiles/log_in.html +20 -0
  64. fnschoo1/profiles/templates/profiles/log_out.html +12 -0
  65. fnschoo1/profiles/tests.py +3 -0
  66. fnschoo1/profiles/urls.py +15 -0
  67. fnschoo1/profiles/views.py +63 -0
  68. fnschoo1/static/css/bootstrap.min.css +11776 -0
  69. fnschoo1/static/css/fnschool.css +26 -0
  70. fnschoo1/static/images/favicon.ico +0 -0
  71. fnschoo1/static/js/bootstrap.bundle.min.js +4223 -0
  72. fnschoo1/static/js/bootstrap.min.js +2919 -0
  73. fnschoo1/static/js/fnschool.js +84 -0
  74. fnschoo1/static/js/jquery.min.js +5413 -0
  75. fnschoo1/static/js/jquery.slim.min.js +4331 -0
  76. fnschoo1/static/js/popper.min.js +1306 -0
  77. fnschoo1/static_collected/admin/css/autocomplete.css +377 -0
  78. fnschoo1/static_collected/admin/css/base.css +1224 -0
  79. fnschoo1/static_collected/admin/css/changelists.css +334 -0
  80. fnschoo1/static_collected/admin/css/dark_mode.css +136 -0
  81. fnschoo1/static_collected/admin/css/dashboard.css +30 -0
  82. fnschoo1/static_collected/admin/css/forms.css +546 -0
  83. fnschoo1/static_collected/admin/css/login.css +62 -0
  84. fnschoo1/static_collected/admin/css/nav_sidebar.css +145 -0
  85. fnschoo1/static_collected/admin/css/responsive.css +1043 -0
  86. fnschoo1/static_collected/admin/css/responsive_rtl.css +84 -0
  87. fnschoo1/static_collected/admin/css/rtl.css +311 -0
  88. fnschoo1/static_collected/admin/css/vendor/select2/select2.css +708 -0
  89. fnschoo1/static_collected/admin/css/vendor/select2/select2.min.css +1 -0
  90. fnschoo1/static_collected/admin/css/widgets.css +639 -0
  91. fnschoo1/static_collected/admin/js/SelectBox.js +128 -0
  92. fnschoo1/static_collected/admin/js/SelectFilter2.js +503 -0
  93. fnschoo1/static_collected/admin/js/actions.js +232 -0
  94. fnschoo1/static_collected/admin/js/admin/DateTimeShortcuts.js +496 -0
  95. fnschoo1/static_collected/admin/js/admin/RelatedObjectLookups.js +276 -0
  96. fnschoo1/static_collected/admin/js/autocomplete.js +33 -0
  97. fnschoo1/static_collected/admin/js/calendar.js +251 -0
  98. fnschoo1/static_collected/admin/js/cancel.js +29 -0
  99. fnschoo1/static_collected/admin/js/change_form.js +21 -0
  100. fnschoo1/static_collected/admin/js/collapse.js +43 -0
  101. fnschoo1/static_collected/admin/js/core.js +174 -0
  102. fnschoo1/static_collected/admin/js/filters.js +37 -0
  103. fnschoo1/static_collected/admin/js/inlines.js +439 -0
  104. fnschoo1/static_collected/admin/js/jquery.init.js +8 -0
  105. fnschoo1/static_collected/admin/js/nav_sidebar.js +81 -0
  106. fnschoo1/static_collected/admin/js/popup_response.js +24 -0
  107. fnschoo1/static_collected/admin/js/prepopulate.js +43 -0
  108. fnschoo1/static_collected/admin/js/prepopulate_init.js +20 -0
  109. fnschoo1/static_collected/admin/js/theme.js +57 -0
  110. fnschoo1/static_collected/admin/js/urlify.js +529 -0
  111. fnschoo1/static_collected/admin/js/vendor/jquery/jquery.js +10913 -0
  112. fnschoo1/static_collected/admin/js/vendor/jquery/jquery.min.js +2 -0
  113. fnschoo1/static_collected/admin/js/vendor/select2/i18n/af.js +43 -0
  114. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ar.js +36 -0
  115. fnschoo1/static_collected/admin/js/vendor/select2/i18n/az.js +33 -0
  116. fnschoo1/static_collected/admin/js/vendor/select2/i18n/bg.js +38 -0
  117. fnschoo1/static_collected/admin/js/vendor/select2/i18n/bn.js +39 -0
  118. fnschoo1/static_collected/admin/js/vendor/select2/i18n/bs.js +48 -0
  119. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ca.js +41 -0
  120. fnschoo1/static_collected/admin/js/vendor/select2/i18n/cs.js +62 -0
  121. fnschoo1/static_collected/admin/js/vendor/select2/i18n/da.js +37 -0
  122. fnschoo1/static_collected/admin/js/vendor/select2/i18n/de.js +41 -0
  123. fnschoo1/static_collected/admin/js/vendor/select2/i18n/dsb.js +51 -0
  124. fnschoo1/static_collected/admin/js/vendor/select2/i18n/el.js +43 -0
  125. fnschoo1/static_collected/admin/js/vendor/select2/i18n/en.js +41 -0
  126. fnschoo1/static_collected/admin/js/vendor/select2/i18n/es.js +41 -0
  127. fnschoo1/static_collected/admin/js/vendor/select2/i18n/et.js +38 -0
  128. fnschoo1/static_collected/admin/js/vendor/select2/i18n/eu.js +45 -0
  129. fnschoo1/static_collected/admin/js/vendor/select2/i18n/fa.js +42 -0
  130. fnschoo1/static_collected/admin/js/vendor/select2/i18n/fi.js +42 -0
  131. fnschoo1/static_collected/admin/js/vendor/select2/i18n/fr.js +43 -0
  132. fnschoo1/static_collected/admin/js/vendor/select2/i18n/gl.js +40 -0
  133. fnschoo1/static_collected/admin/js/vendor/select2/i18n/he.js +44 -0
  134. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hi.js +40 -0
  135. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hr.js +45 -0
  136. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hsb.js +51 -0
  137. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hu.js +44 -0
  138. fnschoo1/static_collected/admin/js/vendor/select2/i18n/hy.js +40 -0
  139. fnschoo1/static_collected/admin/js/vendor/select2/i18n/id.js +36 -0
  140. fnschoo1/static_collected/admin/js/vendor/select2/i18n/is.js +37 -0
  141. fnschoo1/static_collected/admin/js/vendor/select2/i18n/it.js +43 -0
  142. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ja.js +40 -0
  143. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ka.js +42 -0
  144. fnschoo1/static_collected/admin/js/vendor/select2/i18n/km.js +38 -0
  145. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ko.js +42 -0
  146. fnschoo1/static_collected/admin/js/vendor/select2/i18n/lt.js +45 -0
  147. fnschoo1/static_collected/admin/js/vendor/select2/i18n/lv.js +41 -0
  148. fnschoo1/static_collected/admin/js/vendor/select2/i18n/mk.js +42 -0
  149. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ms.js +38 -0
  150. fnschoo1/static_collected/admin/js/vendor/select2/i18n/nb.js +38 -0
  151. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ne.js +44 -0
  152. fnschoo1/static_collected/admin/js/vendor/select2/i18n/nl.js +46 -0
  153. fnschoo1/static_collected/admin/js/vendor/select2/i18n/pl.js +43 -0
  154. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ps.js +41 -0
  155. fnschoo1/static_collected/admin/js/vendor/select2/i18n/pt-BR.js +39 -0
  156. fnschoo1/static_collected/admin/js/vendor/select2/i18n/pt.js +41 -0
  157. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ro.js +43 -0
  158. fnschoo1/static_collected/admin/js/vendor/select2/i18n/ru.js +48 -0
  159. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sk.js +61 -0
  160. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sl.js +41 -0
  161. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sq.js +43 -0
  162. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sr-Cyrl.js +48 -0
  163. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sr.js +48 -0
  164. fnschoo1/static_collected/admin/js/vendor/select2/i18n/sv.js +40 -0
  165. fnschoo1/static_collected/admin/js/vendor/select2/i18n/th.js +36 -0
  166. fnschoo1/static_collected/admin/js/vendor/select2/i18n/tk.js +36 -0
  167. fnschoo1/static_collected/admin/js/vendor/select2/i18n/tr.js +40 -0
  168. fnschoo1/static_collected/admin/js/vendor/select2/i18n/uk.js +59 -0
  169. fnschoo1/static_collected/admin/js/vendor/select2/i18n/vi.js +37 -0
  170. fnschoo1/static_collected/admin/js/vendor/select2/i18n/zh-CN.js +36 -0
  171. fnschoo1/static_collected/admin/js/vendor/select2/i18n/zh-TW.js +33 -0
  172. fnschoo1/static_collected/admin/js/vendor/select2/select2.full.js +7115 -0
  173. fnschoo1/static_collected/admin/js/vendor/select2/select2.full.min.js +2 -0
  174. fnschoo1/static_collected/admin/js/vendor/xregexp/xregexp.js +4993 -0
  175. fnschoo1/static_collected/admin/js/vendor/xregexp/xregexp.min.js +160 -0
  176. fnschoo1/static_collected/css/bootstrap.min.css +11776 -0
  177. fnschoo1/static_collected/css/fnschool.css +26 -0
  178. fnschoo1/static_collected/images/favicon.ico +0 -0
  179. fnschoo1/static_collected/js/bootstrap.bundle.min.js +4223 -0
  180. fnschoo1/static_collected/js/bootstrap.min.js +2919 -0
  181. fnschoo1/static_collected/js/fnschool.js +84 -0
  182. fnschoo1/static_collected/js/jquery.min.js +5413 -0
  183. fnschoo1/static_collected/js/jquery.slim.min.js +4331 -0
  184. fnschoo1/static_collected/js/popper.min.js +1306 -0
  185. fnschoo1/templates/base/_css.html +1 -0
  186. fnschoo1/templates/base/_js.html +15 -0
  187. fnschoo1/templates/base/content.html +30 -0
  188. fnschoo1/templates/base/header_content_footer.html +35 -0
  189. fnschoo1/templates/close.html +11 -0
  190. fnschoo1/templates/home.html +51 -0
  191. fnschoo1/templates/includes/_footer.html +39 -0
  192. fnschoo1/templates/includes/_header.html +77 -0
  193. fnschoo1/templates/includes/_navigation.html +0 -0
  194. fnschoo1/templates/includes/_paginator.html +27 -0
  195. fnschoo1/templates/registration/logged_out.html +0 -0
  196. fnschoo1/templates/registration/login.html +0 -0
  197. fnschool-20251011.81638.854.dist-info/METADATA +179 -0
  198. fnschool-20251011.81638.854.dist-info/RECORD +209 -0
  199. {fnschool-20250109.80531.837.dist-info → fnschool-20251011.81638.854.dist-info}/WHEEL +1 -1
  200. fnschool-20251011.81638.854.dist-info/entry_points.txt +2 -0
  201. fnschool-20251011.81638.854.dist-info/top_level.txt +1 -0
  202. fnschool/__init__.py +0 -35
  203. fnschool/__main__.py +0 -16
  204. fnschool/app.py +0 -103
  205. fnschool/canteen/__init__.py +0 -3
  206. fnschool/canteen/__main__.py +0 -3
  207. fnschool/canteen/bill.py +0 -253
  208. fnschool/canteen/canteen.py +0 -1
  209. fnschool/canteen/canteen.toml +0 -61
  210. fnschool/canteen/config.py +0 -10
  211. fnschool/canteen/consuming.py +0 -53
  212. fnschool/canteen/currency.py +0 -17
  213. fnschool/canteen/data/bill.i18n.xlsx +0 -0
  214. fnschool/canteen/data/bill.xlsx +0 -0
  215. fnschool/canteen/data/consuming.xlsx +0 -0
  216. fnschool/canteen/data/purchase_list.xlsx +0 -0
  217. fnschool/canteen/entry.py +0 -40
  218. fnschool/canteen/food.py +0 -206
  219. fnschool/canteen/food_classes.py +0 -33
  220. fnschool/canteen/food_classes.toml +0 -64
  221. fnschool/canteen/operator.py +0 -91
  222. fnschool/canteen/path.py +0 -28
  223. fnschool/canteen/spreadsheet/base.py +0 -213
  224. fnschool/canteen/spreadsheet/consuming.py +0 -310
  225. fnschool/canteen/spreadsheet/consumingsum.py +0 -76
  226. fnschool/canteen/spreadsheet/cover.py +0 -64
  227. fnschool/canteen/spreadsheet/ctspreadsheet.py +0 -351
  228. fnschool/canteen/spreadsheet/food.py +0 -680
  229. fnschool/canteen/spreadsheet/inventory.py +0 -375
  230. fnschool/canteen/spreadsheet/merging.py +0 -340
  231. fnschool/canteen/spreadsheet/preconsuming.py +0 -329
  232. fnschool/canteen/spreadsheet/purchasing.py +0 -885
  233. fnschool/canteen/spreadsheet/purchasingsum.py +0 -110
  234. fnschool/canteen/spreadsheet/spreadsheet.py +0 -363
  235. fnschool/canteen/spreadsheet/translating.py +0 -12
  236. fnschool/canteen/spreadsheet/unwarehousing.py +0 -178
  237. fnschool/canteen/spreadsheet/unwarehousingsum.py +0 -11
  238. fnschool/canteen/spreadsheet/warehousing.py +0 -360
  239. fnschool/canteen/spreadsheet/workbook.py +0 -17
  240. fnschool/canteen/test.py +0 -97
  241. fnschool/config.py +0 -48
  242. fnschool/entry.py +0 -67
  243. fnschool/exam/__init__.py +0 -8
  244. fnschool/exam/data/parental_emails.xlsx +0 -0
  245. fnschool/exam/data/score.xlsx +0 -0
  246. fnschool/exam/email.py +0 -349
  247. fnschool/exam/entry.py +0 -36
  248. fnschool/exam/language.py +0 -19
  249. fnschool/exam/path.py +0 -24
  250. fnschool/exam/score.py +0 -1191
  251. fnschool/exam/subject.py +0 -20
  252. fnschool/exam/teacher.py +0 -54
  253. fnschool/external.py +0 -89
  254. fnschool/games/__init__.py +0 -1
  255. fnschool/games/__main__.py +0 -1
  256. fnschool/games/games.py +0 -1
  257. fnschool/inoutput.py +0 -97
  258. fnschool/language.py +0 -40
  259. fnschool/locales/en_US/LC_MESSAGES/fnschool.mo +0 -0
  260. fnschool/locales/zh_CN/LC_MESSAGES/fnschool.mo +0 -0
  261. fnschool/locales/zh_HK/LC_MESSAGES/fnschool.mo +0 -0
  262. fnschool/locales/zh_SG/LC_MESSAGES/fnschool.mo +0 -0
  263. fnschool/locales/zh_TW/LC_MESSAGES/fnschool.mo +0 -0
  264. fnschool/path.py +0 -45
  265. fnschool/test.py +0 -24
  266. fnschool/user.py +0 -262
  267. fnschool-20250109.80531.837.dist-info/METADATA +0 -342
  268. fnschool-20250109.80531.837.dist-info/RECORD +0 -78
  269. fnschool-20250109.80531.837.dist-info/entry_points.txt +0 -5
  270. fnschool-20250109.80531.837.dist-info/top_level.txt +0 -1
  271. /fnschool/canteen/consume.py → /fnschoo1/canteen/__init__.py +0 -0
  272. /fnschool/canteen/food_recount.toml → /fnschoo1/canteen/migrations/__init__.py +0 -0
  273. {fnschool/canteen/spreadsheet → fnschoo1/canteen/workbook}/__init__.py +0 -0
  274. /fnschool/exam/__main__.py → /fnschoo1/fnschool/templatetags/__init__.py +0 -0
  275. /fnschool/canteen/food_recounts.toml → /fnschoo1/profiles/__init__.py +0 -0
  276. /fnschool/canteen/warehouse.py → /fnschoo1/profiles/migrations/__init__.py +0 -0
  277. /fnschool/canteen/workbook.toml → /fnschoo1/templates/base/_content.html +0 -0
  278. {fnschool-20250109.80531.837.dist-info → fnschool-20251011.81638.854.dist-info/licenses}/LICENSE +0 -0
@@ -1,375 +0,0 @@
1
- import os
2
- import sys
3
- import re
4
- import calendar
5
- from datetime import datetime
6
- from fnschool import *
7
- from fnschool.canteen.food import Food
8
- from fnschool.canteen.spreadsheet.base import *
9
-
10
-
11
- class Inventory(Base):
12
- def __init__(self, bill):
13
- super().__init__(bill)
14
- self.sheet_name = self.s.inventory_name
15
- self.entry_row_len0 = 17
16
- pass
17
-
18
- def get_entry_index(self, form_index):
19
- form_index0, form_index1 = form_index
20
- entry_index = [form_index0 + 4, form_index1 - 3]
21
- return entry_index
22
-
23
- def format(self):
24
- sheet = self.sheet
25
- self.unmerge_sheet_cells(sheet)
26
-
27
- for row in sheet.iter_rows(
28
- min_row=1, max_row=sheet.max_row, min_col=1, max_col=9
29
- ):
30
- sheet.row_dimensions[row[0].row].height = 14.25
31
-
32
- if row[8].value and "原因" in str(row[8].value).replace(" ", ""):
33
- sheet.merge_cells(
34
- start_row=row[0].row,
35
- end_row=row[0].row + 1,
36
- start_column=9,
37
- end_column=9,
38
- )
39
-
40
- if row[6].value and str(row[6].value).replace(" ", "") == "差额栏":
41
- sheet.merge_cells(
42
- start_row=row[0].row,
43
- end_row=row[0].row,
44
- start_column=7,
45
- end_column=8,
46
- )
47
-
48
- if row[4].value and str(row[4].value).replace(" ", "") == "盘点栏":
49
- sheet.merge_cells(
50
- start_row=row[0].row,
51
- end_row=row[0].row,
52
- start_column=5,
53
- end_column=6,
54
- )
55
-
56
- if row[2].value and str(row[2].value).replace(" ", "") == "账面栏":
57
- sheet.merge_cells(
58
- start_row=row[0].row,
59
- end_row=row[0].row,
60
- start_column=3,
61
- end_column=4,
62
- )
63
-
64
- if row[0].value and row[0].value.replace(" ", "") == "食材名称":
65
- sheet.merge_cells(
66
- start_row=row[0].row,
67
- end_row=row[0].row + 1,
68
- start_column=1,
69
- end_column=1,
70
- )
71
-
72
- if row[0].value and (
73
- "备注" in row[0].value.replace(" ", "")
74
- or "审核人" in row[0].value.replace(" ", "")
75
- ):
76
- sheet.merge_cells(
77
- start_row=row[0].row,
78
- end_row=row[0].row,
79
- start_column=1,
80
- end_column=9,
81
- )
82
-
83
- if row[0].value and row[0].value.replace(" ", "") == "食材盘存表":
84
- sheet.merge_cells(
85
- start_row=row[0].row,
86
- end_row=row[0].row,
87
- start_column=1,
88
- end_column=9,
89
- )
90
- sheet.row_dimensions[row[0].row].height = 22.5
91
-
92
- sheet.merge_cells(
93
- start_row=row[0].row + 1,
94
- end_row=row[0].row + 1,
95
- start_column=1,
96
- end_column=9,
97
- )
98
-
99
- print_info(_('Sheet "{0}" has been reformatted.').format(sheet.title))
100
-
101
- @property
102
- def form_indexes(self):
103
- if not self._form_indexes:
104
- sheet = self.sheet
105
- indexes = []
106
- for row in sheet.iter_rows(max_row=sheet.max_row + 1, max_col=8):
107
- if row[0].value:
108
- cell0_value = str(row[0].value).replace(" ", "")
109
- if "食材盘存表" in cell0_value:
110
- indexes.append([row[0].row, 0])
111
- if "审核人" in cell0_value:
112
- indexes[-1][1] = row[0].row
113
-
114
- self._form_indexes = indexes
115
-
116
- return self._form_indexes
117
-
118
- @property
119
- def saved_foods(self):
120
- _foods = self.get_save_foods()
121
- return _foods
122
-
123
- def get_save_foods(self, meal_type=None):
124
- bill_fpath = self.bill.operator.get_bill_fpath(meal_type)
125
- wb = load_workbook(bill_fpath, read_only=True)
126
- sheet = wb[self.sheet_name]
127
- purchasing = self.bill.spreadsheet.purchasing
128
-
129
- food_index_m1 = []
130
-
131
- for row_index in range(1, sheet.max_row):
132
- if "食材名称" in str(sheet.cell(row_index, 1).value):
133
- if sheet.cell(row_index + 2, 1).value:
134
- food_index_m1 = [row_index + 2, None]
135
- else:
136
- break
137
- if "合计" in str(sheet.cell(row_index, 1).value):
138
- food_index_m1[1] = row_index - 1
139
-
140
- if len(food_index_m1) < 1:
141
- return []
142
-
143
- foods = []
144
- header_info = str(sheet.cell(food_index_m1[0] - 3, 1).value)
145
- header_info0 = header_info.replace(" ", "")
146
-
147
- purchaser = re.split(r"\d+", re.split(r":\s*", header_info0)[1])[0]
148
- year = int(
149
- re.split(r"\D+", re.split(r"年", header_info0)[0].strip())[-1]
150
- )
151
- month = int(re.split(r"月", re.split(r"年", header_info0)[-1])[0])
152
- day = int(re.split(r"月", re.split(r"日", header_info0)[0])[-1])
153
-
154
- for row_index in range(food_index_m1[0], food_index_m1[1] + 1):
155
- fname = sheet.cell(row_index, 1).value
156
- if not fname:
157
- break
158
- funit_name = sheet.cell(row_index, 2).value or _("No unit")
159
- fcount = float(sheet.cell(row_index, 5).value)
160
- ftotal_price = float(sheet.cell(row_index, 6).value)
161
-
162
- food = Food(
163
- self.bill,
164
- name=fname,
165
- unit_name=funit_name,
166
- fclass=purchasing.get_food_class(fname),
167
- count=fcount,
168
- total_price=ftotal_price,
169
- xdate=f"{year}-{month}-{day}",
170
- purchaser=purchaser,
171
- is_inventory=True,
172
- is_abandoned=False,
173
- )
174
- foods.append(food)
175
- if len(foods) < 1:
176
- return None
177
- return foods
178
-
179
- @property
180
- def foods(self):
181
- tnfoods = []
182
- bfoods = self.bfoods.copy()
183
- bfoods = [f for f in bfoods if not f.is_abandoned]
184
- year = self.bill.consuming.year
185
- month = self.bill.consuming.month
186
-
187
- consuming_dates = []
188
- for bfood in bfoods:
189
- for d, __ in bfood.consumptions:
190
- consuming_dates.append(d)
191
- consuming_dates = list(set(consuming_dates))
192
-
193
- for tn in calendar.monthcalendar(year, month):
194
- if 0 in tn:
195
- tn = list(set(tn))
196
- tn.remove(0)
197
- tn0, tn1 = tn[0], tn[-1]
198
- for d in range(tn1, tn0 - 1, -1):
199
- d_date = datetime(year, month, d)
200
- if d_date in consuming_dates:
201
- tnfoods.append(
202
- [
203
- d_date,
204
- [
205
- f
206
- for f in bfoods
207
- if (
208
- f.get_remainder(d_date) > 0
209
- and f.xdate != d_date
210
- )
211
- ],
212
- ]
213
- )
214
- break
215
- ifoods = [f for f in bfoods if f.is_inventory]
216
- if len(ifoods) > 0:
217
- tnfoods = [[ifoods[0].xdate, ifoods]] + tnfoods
218
-
219
- return tnfoods
220
-
221
- def update(self):
222
- sheet = self.sheet
223
- tnfoods = self.foods
224
- form_indexes = self.form_indexes
225
- self.unmerge_sheet_cells()
226
-
227
- for form_index_n in range(0, len(form_indexes)):
228
- form_index = form_indexes[form_index_n]
229
- form_index0, form_index1 = form_index
230
- food_index0, food_index1 = self.get_entry_index(form_index)
231
- for row in sheet.iter_rows(
232
- min_row=food_index0,
233
- max_row=food_index1,
234
- min_col=1,
235
- max_col=9,
236
- ):
237
- for cell in row:
238
- cell.value = ""
239
-
240
- for i, (t1, _foods) in enumerate(tnfoods):
241
-
242
- if len(_foods) < 1:
243
- print_warning(
244
- _('There is no inventories for "{0}".').format(
245
- t1.strftime("%Y-%m-%d")
246
- )
247
- )
248
- continue
249
-
250
- form_indexes_n = i
251
- form_index = form_indexes[form_indexes_n]
252
- form_i0, form_i1 = form_index
253
- fentry_i0, fentry_i1 = self.get_entry_index(form_index)
254
-
255
- sheet.cell(
256
- form_i0 + 1,
257
- 1,
258
- f" "
259
- + f"学校名称:{self.purchaser}"
260
- + f" "
261
- + f"{t1.year} 年 {t1.month} 月 {t1.day} 日"
262
- + f" ",
263
- )
264
- sheet.cell(
265
- form_i1,
266
- 1,
267
- (
268
- " "
269
- + "审核人:"
270
- + " "
271
- + "经办人:"
272
- + self.operator.name
273
- + "  "
274
- + "过称人:"
275
- + " "
276
- + "仓管人:"
277
- + "   "
278
- ),
279
- )
280
- rtotal_price = sum(
281
- [f.get_remainder(t1) * f.unit_price for f in _foods]
282
- )
283
- sheet.cell(form_i1 - 2, 4, rtotal_price)
284
- sheet.cell(form_i1 - 2, 6, rtotal_price)
285
-
286
- for row in sheet.iter_rows(
287
- min_row=fentry_i0,
288
- max_row=fentry_i1,
289
- min_col=1,
290
- max_col=9,
291
- ):
292
- for cell in row:
293
- cell.value = ""
294
- cell.alignment = self.cell_alignment0
295
- cell.border = self.cell_border0
296
-
297
- writed_foods = []
298
- row_offset = 0
299
- for findex, food in enumerate(_foods):
300
- row_index = fentry_i0 + findex + row_offset
301
- if sheet.cell(row_index + 1, 1).value and (
302
- sheet.cell(row_index + 1, 1).value.replace(" ", "")
303
- == "合计"
304
- ):
305
- i_row_index = row_index + 1
306
- self.row_inserting_tip(i_row_index)
307
- sheet.insert_rows(i_row_index, 1)
308
-
309
- for i_col_index in range(1, 10):
310
- cell = sheet.cell(i_row_index, i_col_index)
311
- cell.alignment = self.cell_alignment0
312
- cell.border = self.cell_border0
313
-
314
- self.del_form_indexes()
315
- form_indexes = self.form_indexes
316
-
317
- unit_price = food.unit_price
318
-
319
- writed_food_names = [wname for wname, wrow in writed_foods]
320
- if not food.name in writed_food_names:
321
-
322
- sheet.cell(row_index, 1, food.name)
323
- sheet.cell(row_index, 2, food.unit_name)
324
-
325
- sheet.cell(row_index, 3, food.get_remainder(t1))
326
- sheet.cell(row_index, 5, food.get_remainder(t1))
327
-
328
- f_total_price = food.get_remainder(t1) * unit_price
329
- sheet.cell(row_index, 4, f_total_price)
330
- sheet.cell(row_index, 6, f_total_price)
331
-
332
- writed_foods.append((food.name, row_index))
333
- pass
334
-
335
- else:
336
- wrow_index = [r for n, r in writed_foods if n == food.name][
337
- 0
338
- ]
339
- rcell2_value = str(sheet.cell(wrow_index, 3).value).replace(
340
- " ", ""
341
- )
342
-
343
- rcell3_value = str(sheet.cell(wrow_index, 4).value).replace(
344
- " ", ""
345
- )
346
-
347
- if rcell2_value.replace(".", "").isnumeric():
348
- rcell2_value = float(rcell2_value)
349
- rcell2_value += food.get_remainder(t1)
350
- sheet.cell(wrow_index, 3, rcell2_value)
351
- sheet.cell(wrow_index, 5, rcell2_value)
352
- pass
353
-
354
- if rcell3_value.replace(".", "").isnumeric():
355
- rcell3_value = float(rcell3_value)
356
- rcell3_value += food.get_remainder(t1) * unit_price
357
- sheet.cell(wrow_index, 4, rcell3_value)
358
- sheet.cell(wrow_index, 6, rcell3_value)
359
- pass
360
- row_offset -= 1
361
- pass
362
-
363
- pass
364
-
365
- pass
366
-
367
- self.del_form_empty_rows([1])
368
- self.format()
369
-
370
- wb = self.bwb
371
- wb.active = sheet
372
- print_info(_("Sheet '%s' was updated.") % (self.sheet_name))
373
-
374
-
375
- # The end.
@@ -1,340 +0,0 @@
1
- import os
2
- import random
3
- import sys
4
- from pathlib import Path
5
- import shutil
6
- import secrets
7
- import calendar
8
- import pandas as pd
9
- from datetime import datetime, timedelta
10
- import numpy as np
11
-
12
- import tkinter as tk
13
- from tkinter import filedialog, ttk
14
-
15
- from fnschool import *
16
- from fnschool.canteen.food import *
17
- from fnschool.canteen.path import *
18
-
19
- from fnschool.canteen.spreadsheet.base import Base
20
- from fnschool.canteen.spreadsheet.food import Food as FoodSheet
21
-
22
-
23
- class Merging(Base):
24
- def __init__(self, bill):
25
- super().__init__(bill)
26
- self._last_fpath = None
27
- self._current_fpath = None
28
- self.last_fpath_dpath_key = _("last_bill_dpath")
29
- self.current_fpath_dpath_key = _("current_bill_dpath")
30
- self._last_wb = None
31
- self._current_wb = None
32
- self._food_sheet = None
33
- self.cover_sheet_title = self.s.cover_name
34
- pass
35
-
36
- @property
37
- def food_sheet(self):
38
- if not self._food_sheet:
39
- self._food_sheet = FoodSheet(self.bill)
40
- return self._food_sheet
41
-
42
- @property
43
- def last_wb(self):
44
- if not self._last_wb:
45
- print_info(_('Loading data from "{0}".').format(self.last_fpath))
46
- wb = load_workbook(self.last_fpath, data_only=True)
47
- self._last_wb = wb
48
- return self._last_wb
49
-
50
- @property
51
- def current_wb(self):
52
- if not self._current_wb:
53
- print_info(_('Loading data from "{0}".').format(self.current_fpath))
54
- wb = load_workbook(self.current_fpath)
55
- self._current_wb = wb
56
- return self._current_wb
57
-
58
- @current_wb.setter
59
- def current_wb(self, wb):
60
- self._current_wb = wb
61
- pass
62
-
63
- @property
64
- def last_fpath(self):
65
- if not self._last_fpath:
66
- root = tk.Tk()
67
- root.withdraw()
68
- conf_initialdir = self.config.get(self.last_fpath_dpath_key)
69
- conf_initialdir = Path(conf_initialdir) if conf_initialdir else None
70
- initialdir = conf_initialdir or documents_dpath or Path.home()
71
- fpath = filedialog.askopenfilename(
72
- parent=root,
73
- title=_("Select the last bill spreadsheet"),
74
- initialdir=initialdir,
75
- filetypes=self.filetypes_xlsx,
76
- )
77
- if not fpath:
78
- print_error(_("there is not file selected. Exit."))
79
- exit()
80
- else:
81
- fpath = Path(fpath)
82
-
83
- if not conf_initialdir == fpath:
84
- self.config.save(
85
- self.last_fpath_dpath_key, fpath.parent.as_posix()
86
- )
87
- self._last_fpath = fpath
88
-
89
- return self._last_fpath
90
- pass
91
-
92
- @property
93
- def current_fpath(self):
94
- if not self._current_fpath:
95
- root = tk.Tk()
96
- root.withdraw()
97
- conf_initialdir = self.config.get(self.current_fpath_dpath_key)
98
- conf_initialdir = Path(conf_initialdir) if conf_initialdir else None
99
- initialdir = conf_initialdir or documents_dpath or Path.home()
100
- fpath = filedialog.askopenfilename(
101
- parent=root,
102
- title=_("Select the current bill spreadsheet"),
103
- initialdir=initialdir,
104
- filetypes=self.filetypes_xlsx,
105
- )
106
-
107
- if not fpath:
108
- print_error(_("there is not file selected. Exit."))
109
- exit()
110
- else:
111
- fpath = Path(fpath)
112
-
113
- if not conf_initialdir == fpath:
114
- self.config.save(
115
- self.current_fpath_dpath_key, fpath.parent.as_posix()
116
- )
117
-
118
- self._current_fpath = fpath
119
- return self._current_fpath
120
- pass
121
-
122
- def get_food_sheet_names(self, wb):
123
- names = []
124
- for name in wb.sheetnames:
125
- sheet = wb[name]
126
- if sheet.cell(1, 1).value and self.food_form_title_like in str(
127
- sheet.cell(1, 1).value
128
- ):
129
- names.append(name)
130
-
131
- if self.food_sheet0_name in names:
132
- names.remove(self.food_sheet0_name)
133
-
134
- return names
135
-
136
- @current_fpath.setter
137
- def current_fpath(self, fpath):
138
- self._current_fpath = fpath
139
- pass
140
-
141
- def get_sheet(self, name=None, wb=None):
142
- sheet = None
143
- wb = wb or self.bwb
144
-
145
- if name in wb.sheetnames:
146
- sheet = wb[name]
147
- else:
148
- sheet = wb.copy_worksheet(wb[self.sheet_name])
149
- sheet.title = name
150
-
151
- for row_index in range(1, sheet.max_row + 1):
152
- rc1_value = sheet.cell(row_index, 1).value
153
- rc1_value = str(rc1_value)
154
- if rc1_value and "材料名称:()" in rc1_value:
155
- unit = [f.unit_name for f in bfoods if f.name == name]
156
- unit = unit[0] if len(unit) > 0 else "斤"
157
- sheet.cell(
158
- row_index, 1, "材料名称:{0}({1})".format(name, unit)
159
- )
160
-
161
- return sheet
162
-
163
- def get_data_rows_list(self, sheet):
164
- rows = []
165
- for row in sheet.iter_rows(
166
- min_row=1, max_row=sheet.max_row, min_col=1, max_col=14
167
- ):
168
- cell3 = row[2]
169
- if "摘要" in str(cell3.value):
170
- rows.append([cell3.row + 1, None])
171
- continue
172
- elif "本月合计" in str(cell3.value):
173
- row_m1 = rows[-1]
174
- row_m1[-1] = cell3.row - 1
175
- rows[-1] = row_m1
176
- continue
177
- pass
178
- return rows
179
-
180
- def make_row_counts_same(self, last_sheet, current_sheet):
181
- lsheet = last_sheet
182
- csheet = current_sheet
183
- ldata_rows = self.get_data_rows_list(lsheet)
184
- cdata_rows = self.get_data_rows_list(csheet)
185
-
186
- for i, (crow0, crow1) in enumerate(cdata_rows):
187
- lrow0, lrow1 = ldata_rows[i]
188
- row_diff = (lrow1 - lrow0) - (crow1 - crow0)
189
- if row_diff > 0:
190
- csheet.insert_rows(crow0 + 1, row_diff)
191
- for row_index_f in range(crow0 + 1, crow0 + 1 + row_diff):
192
- for col_index_f in range(1, 14):
193
- cell = csheet.cell(row_index_f, col_index_f)
194
- cell.border = self.cell_border0
195
- cell.alignment = self.cell_alignment0
196
- self.make_row_counts_same(lsheet, csheet)
197
- break
198
- elif row_diff < 0:
199
- row_diff = abs(row_diff)
200
- csheet.delete_rows(lrow0 + 1, row_diff)
201
- self.make_row_counts_same(lsheet, csheet)
202
- break
203
-
204
- pass
205
-
206
- pass
207
-
208
- def start(self, current_wb=[None, None]):
209
- lwb = self.last_wb
210
-
211
- if current_wb:
212
- current_wb, current_fpath = current_wb
213
-
214
- self.current_fpath = current_fpath
215
- self.current_wb = current_wb
216
-
217
- cwb = self.current_wb
218
-
219
- lwb_sheet_names = self.get_food_sheet_names(lwb)
220
- cwb_sheet_names = self.get_food_sheet_names(cwb)
221
-
222
- names_len = len(lwb_sheet_names)
223
- names_len2 = len(str(names_len))
224
- name_index = 0
225
-
226
- for name in lwb_sheet_names:
227
- lsheet = None
228
- csheet = None
229
- if not name in cwb_sheet_names:
230
- lsheet = lwb[name]
231
- csheet = cwb.create_sheet(lsheet.title, -1)
232
- for row in lsheet.iter_rows(max_col=13):
233
- for lcell in row:
234
- ccell = csheet.cell(lcell.row, lcell.column)
235
- ccell.value = lcell.value
236
- ccell.alignment = self.cell_alignment0
237
- ccell.border = self.cell_border0
238
- csheet.row_dimensions[row[0].row].height = self.row_height
239
- self.food_sheet.format(csheet)
240
- pass
241
- else:
242
- lsheet = lwb[name]
243
- csheet = cwb[name]
244
-
245
- self.unmerge_sheet_cells(csheet)
246
-
247
- self.make_row_counts_same(lsheet, csheet)
248
- ldata_rows = self.get_data_rows_list(lsheet)
249
- cdata_rows = self.get_data_rows_list(csheet)
250
- row_offset = 2
251
-
252
- for (lrow0, lrow1), (crow0, crow1) in list(
253
- zip(ldata_rows, cdata_rows)
254
- ):
255
- for row_i in range(lrow1 + row_offset - lrow0):
256
- lrow = lrow0 + row_i
257
- crow = crow0 + row_i
258
-
259
- for col_i in range(1, 14):
260
-
261
- cell_value = csheet.cell(crow, col_i).value
262
-
263
- if not (
264
- cell_value
265
- or str(cell_value)
266
- .replace(" ", "")
267
- .replace(" ", "")
268
- == ""
269
- ):
270
- ccell = csheet.cell(
271
- crow,
272
- col_i,
273
- )
274
- lcell_value = lsheet.cell(lrow, col_i).value
275
- ccell.value = lcell_value
276
- pass
277
-
278
- if str(cell_value).startswith("="):
279
- csheet.cell(crow, col_i, "")
280
-
281
- csheet.row_dimensions[crow0 + row_i].height = (
282
- self.row_height
283
- )
284
-
285
- pass
286
-
287
- pass
288
- pass
289
-
290
- self.update_food_sheet_year(csheet)
291
-
292
- name_index += 1
293
- print(
294
- Fore.RED
295
- + f"[{name_index:>{names_len2}}/{names_len}] "
296
- + Style.RESET_ALL
297
- + Fore.GREEN
298
- + _(
299
- 'Data from Sheet "{0}" of Workbook "{1}" was '
300
- + 'copied to Sheet"{2}" of Workbook "{3}".'
301
- ).format(
302
- lsheet.title,
303
- self.last_fpath,
304
- csheet.title,
305
- self.current_fpath,
306
- )
307
- + Style.RESET_ALL
308
- )
309
-
310
- self.food_sheet.update_summation(csheet)
311
- self.food_sheet.update_inventories(csheet)
312
-
313
- csheet.sheet_properties.tabColor = secrets.token_hex(4)
314
- print_info(
315
- _('Food sheet "{0}" has its color recolor.').format(
316
- csheet.title
317
- )
318
- )
319
-
320
- self.food_sheet.format(csheet)
321
-
322
- lsheet = None
323
- csheet = None
324
-
325
- pass
326
-
327
- print_info(
328
- _('Merge completed!Saving "{0}".').format(self.current_fpath)
329
- )
330
- cwb.save(self.current_fpath)
331
-
332
- lwb = None
333
- cwb = None
334
-
335
- open_path(self.current_fpath)
336
-
337
- pass
338
-
339
-
340
- # The end.