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
@@ -0,0 +1,456 @@
1
+ {% extends "base/header_content_footer.html" %}
2
+ {% load crispy_forms_tags %}
3
+ {% block title %}
4
+ {% trans "Consume Ingredients" %}
5
+ {% endblock %}
6
+ {% block content %}
7
+ <h1>{% trans "Consume Ingredients" %}</h1>
8
+ <hr>
9
+ <div class="container">
10
+ <div class="row justify-content-end">
11
+ <div class="col col-3 col-md-2 col-lg-2">
12
+ <input class=" form-control"
13
+ onkeydown="if(event.keyCode==13){list_consumptions();}"
14
+ title="{% trans 'The starting date of storage.' %}"
15
+ id="storage_date_start"
16
+ value="{{ request.COOKIES.storage_date_start }}">
17
+ </input>
18
+ </div>
19
+ <div class="col col-3 col-md-2 col-lg-2">
20
+ <input class="form-control "
21
+ onkeydown="if(event.keyCode==13){list_consumptions();}"
22
+ title="{% trans 'The end date of storage.' %}"
23
+ id="storage_date_end"
24
+ value="{{ request.COOKIES.storage_date_end }}">
25
+ </input>
26
+ </div>
27
+ <button class="btn btn-success col-md-1 col-lg-1 col-2"
28
+ onclick="list_consumptions();">{% trans "Refresh" %}</button>
29
+ </div>
30
+ </div>
31
+ <div class="table table-responsive table-container">
32
+ <table class="table table-consumptions cotable-bordered table-striped table-hover table-condensed scroll-vertical ">
33
+ <thead>
34
+ <tr>
35
+ {% if ingredients %}
36
+ <th class="">{% trans "Ingredient Name" %}</th>
37
+ <th class="">{% trans "Remaining Quantity" %}</th>
38
+ {% endif %}
39
+ {% for date_h in date_range %}
40
+ <th data-date_of_using="{{ date_h }}" class="consumption-date">{{ date_h }}</th>
41
+ {% empty %}
42
+ <th></th>
43
+ {% endfor %}
44
+ </tr>
45
+ </thead>
46
+ <tbody>
47
+ {% for ingredient in ingredients %}
48
+ <tr class="row-consumption"
49
+ data-ingredient_id="{{ ingredient.id }}"
50
+ data-ingredient_name="{{ ingredient.name }}"
51
+ data-ingredient_quantity="{{ ingredient.quantity }}"
52
+ data-ingredient_total_price="{{ ingredient.total_price }}"
53
+ data-ingredient_meal_type="{{ ingredient.meal_type }}"
54
+ data-ingredient_quantity_unit_name="{{ ingredient.quantity_unit_name }}"
55
+ data-ingredient_unit_price="{{ ingredient.unit_price }}"
56
+ id="ingredient_num_{{ ingredient.id }}">
57
+ <td title="{% blocktrans with storage_date=ingredient.storage_date %}Storaged on {{ storage_date }} .{% endblocktrans %}"
58
+ class="">
59
+ <div class='ingredient-progress'
60
+ style="width:{% widthratio ingredient.remaining_quantity ingredient.quantity 100 %}%"></div>
61
+ {{ ingredient.name }}
62
+ {% if ingredient.meal_type %}
63
+ <br />
64
+ ({{ ingredient.meal_type }})
65
+ {% endif %}
66
+ </td>
67
+ <td name="remaining_{{ ingredient.id }}">
68
+ {{ ingredient.quantity }}-{{ ingredient.consuming_quantity }}={{ ingredient.remaining_quantity }}
69
+ </td>
70
+ </tr>
71
+ {% empty %}
72
+ <tr>{% trans "No ingredient found." %}</tr>
73
+ {% endfor %}
74
+ </tbody>
75
+ </table>
76
+ </div>
77
+ <div class="">
78
+ <button onclick="submit_consumptions();"
79
+ class="btn btn-submit-consumptions btn-primary float-start">{% trans "Submit" %}</button>
80
+ <button onclick="generate_spreadsheet();"
81
+ class="btn btn-submit-consumptions btn-success float-end">{% trans "Generate Spreadsheet" %}</button>
82
+ <select class="workbook-month-select form-select float-end mx-2"
83
+ style="width:118px"></select>
84
+ </div>
85
+ {{ ingredient_ids|json_script:'ingredient_ids' }}
86
+ {{ months|json_script:'months' }}
87
+ {{ meal_types|json_script:'meal_types' }}
88
+ {{ date_range|json_script:'date_range' }}
89
+ <script>
90
+ var ingredient_ids = JSON.parse($("#ingredient_ids").text())
91
+ var ingredient_ids_length = ingredient_ids.length
92
+ var months = JSON.parse($("#months").text())
93
+ var meal_types = JSON.parse($("#meal_types").text())
94
+ var dont_submit = false
95
+
96
+ date_range = JSON.parse($("#date_range").text())
97
+
98
+ function get_previous_month_date(date = new Date()) {
99
+ const prevMonthDate = new Date(date);
100
+ prevMonthDate.setDate(1);
101
+ prevMonthDate.setMonth(prevMonthDate.getMonth() - 1);
102
+ return prevMonthDate;
103
+ }
104
+
105
+ function is_weekend(date) {
106
+ const dayOfWeek = date.getDay();
107
+ return dayOfWeek === 0 || dayOfWeek === 6;
108
+ }
109
+
110
+ $(document).ready(function() {
111
+ $(months).each(function(index, value) {
112
+ $('.workbook-month-select').append(`<option>${value}</option>`)
113
+ });
114
+ var now = new Date();
115
+ prev_month = get_previous_month_date(now)
116
+ var year = prev_month.getFullYear();
117
+ var month = prev_month.getMonth() + 1;
118
+ month = month < 10 ? `0${month}` : `${month}`;
119
+ $('.workbook-month-select').val(`${year}-${month}`)
120
+
121
+ });
122
+
123
+
124
+ $(document).ready(function() {
125
+ var last_meal_type = ""
126
+ var consumption_rows = $(".row-consumption")
127
+ consumption_rows.each(function(index, element) {
128
+ meal_type = $(element).data("ingredient_meal_type")
129
+ if (last_meal_type != meal_type) {
130
+ $(element).find("td").css({
131
+ "color": "red"
132
+ })
133
+ last_meal_type = meal_type
134
+ }
135
+ });
136
+ });
137
+
138
+ function amount_used_input_blur(element) {
139
+ element = $(element)
140
+ var ingredient_quantity = element.closest('tr').data("ingredient_quantity")
141
+ ingredient_quantity = parseInt(ingredient_quantity) || 0
142
+ var amount_used = element.closest("form").data("amount_used")
143
+ var new_amount_used = $.trim(element.val())
144
+ new_amount_used = parseInt(new_amount_used) || 0
145
+ if (new_amount_used < 0) {
146
+ element.val('0')
147
+ new_amount_used = 0
148
+ }
149
+ if (new_amount_used === 0 && amount_used == "None") {
150
+ element.val('')
151
+ }
152
+ if (amount_used > 0 && new_amount_used === 0) {
153
+ element.val('0')
154
+ new_amount_used = 0
155
+ }
156
+ var $tds = element.parent().parent().siblings("td")
157
+ var $amount_used_inputs = $tds.find("form input[name='amount_used']")
158
+ var total_consumed = 0
159
+ $amount_used_inputs.each(function(index, amount_used_element) {
160
+ var value = parseInt($(amount_used_element).val()) || 0
161
+ total_consumed += value
162
+ });
163
+ if ((total_consumed + new_amount_used) > ingredient_quantity) {
164
+ var remaining_quantity = total_consumed < ingredient_quantity ? (ingredient_quantity - total_consumed) : 0
165
+ element.val(remaining_quantity)
166
+ new_amount_used = remaining_quantity
167
+ }
168
+ total_consumed = total_consumed + new_amount_used
169
+ var ingredient_id = element.closest("tr").data("ingredient_id")
170
+ $(`td[name='remaining_${ingredient_id}']`).text(`${ingredient_quantity}-${total_consumed}=${ingredient_quantity-total_consumed}`)
171
+ element.closest("tr").find('.ingredient-progress').css('width', `${parseInt((ingredient_quantity-total_consumed)*100/ingredient_quantity)}%`)
172
+ var date_of_using = element.closest("form").data("date_of_using")
173
+ update_header(date_of_using)
174
+ }
175
+
176
+ function update_header(date_of_using) {
177
+ var consumption_content_dated = date_of_using
178
+ $(meal_types).each(function(index, meal_type) {
179
+ var total_price_dated = 0.0
180
+ $(`form[data-date_of_using="${date_of_using}"][data-ingredient_meal_type="${meal_type}"]`).each(function(index, element) {
181
+ element = $(element)
182
+ var unit_price = parseFloat(element.data("ingredient_unit_price"))
183
+ var quantity = parseFloat(element.find("input[name='amount_used']").val()) || 0
184
+ total_price_dated += (unit_price * quantity)
185
+ });
186
+ total_price_dated = total_price_dated.toFixed(2)
187
+ consumption_content_dated += `<br />${meal_type}:${total_price_dated}`
188
+ });
189
+ $(`th[data-date_of_using="${date_of_using}"]`).html(consumption_content_dated)
190
+ }
191
+
192
+ function update_headers() {
193
+
194
+ $(date_range).each(function(index, date_h) {
195
+ update_header(date_h)
196
+ });
197
+ }
198
+
199
+
200
+
201
+ $(document).ready(function() {
202
+ var td1 = $(".table tr > :nth-child(1):first")
203
+ $(".table tr > :nth-child(2)").css("left", td1.width() * 1.05)
204
+ });
205
+
206
+ $(document).ready(function() {
207
+ dont_submit = true
208
+ var progress = 0
209
+ $.each(ingredient_ids, function(index, value) {
210
+ $.ajax({
211
+ url: "/canteen/create_consumption/" + value,
212
+ method: 'GET',
213
+ success: function(data) {
214
+ data = $(data)
215
+ var footer_progressbar = $('.progress-footer')
216
+ data.each(function(index, element) {
217
+ if (is_weekend(new Date($(element).data("date_of_using")))) {
218
+ $(element).find('[name="amount_used"]').addClass("weekend")
219
+ }
220
+ });
221
+ data.find('input[name="amount_used"]').blur(function() {
222
+ amount_used_input_blur(this)
223
+ });
224
+ $('#ingredient_num_' + value).append(data)
225
+ if (footer_progressbar) {
226
+ progress += 1
227
+ footer_progressbar.css('width', `${progress*100/ingredient_ids_length}%`)
228
+ if (progress >= ingredient_ids_length) {
229
+ footer_progressbar.css('width', "0%")
230
+ update_headers()
231
+ dont_submit = false
232
+ }
233
+ }
234
+
235
+ }
236
+ });
237
+ });
238
+ });
239
+
240
+
241
+ $(document).ready(function() {
242
+ $('.table-consumptions').on('keydown', 'input[name="amount_used"]', function(e) {
243
+ if ([9, 13, 37, 38, 39, 40].includes(e.keyCode)) {
244
+ e.preventDefault();
245
+ navigateToNextCell(
246
+ $(this),
247
+ e.keyCode === 9 ? "r" :
248
+ e.keyCode === 13 ? "d" :
249
+ e.keyCode === 37 ? "l" :
250
+ e.keyCode === 38 ? "u" :
251
+ e.keyCode === 39 ? "r" :
252
+ e.keyCode === 40 ? "d" : ""
253
+ );
254
+ }
255
+ if ((e.keyCode < 91 && e.keyCode > 64) || e.keyCode == 32) {
256
+ e.preventDefault()
257
+ }
258
+
259
+ });
260
+
261
+ function navigateToNextCell($currentInput, direction) {
262
+ var td = $currentInput.closest("form").closest('td');
263
+ var columnIndex = td.index();
264
+
265
+ var rowIndex = td.closest("tr").index()
266
+ if (direction == 'l') {
267
+ columnIndex = columnIndex - 1
268
+ rowIndex = rowIndex + 1
269
+ } else if (direction == 'r') {
270
+ columnIndex = columnIndex + 1
271
+ rowIndex = rowIndex + 1
272
+ } else if (direction == "u") {
273
+ rowIndex = rowIndex
274
+ } else if (direction == 'd') {
275
+ rowIndex = rowIndex + 2
276
+ }
277
+ var cell = $('.table-consumptions').find(`tr:eq(${rowIndex}) td:eq(${columnIndex})`);
278
+ var amount_used_input = cell.find('input[name="amount_used"]')
279
+ amount_used_input.first().focus()
280
+
281
+ }
282
+ });
283
+
284
+ function generate_spreadsheet() {
285
+ submit_consumptions(function() {
286
+ var month = $(".workbook-month-select").val()
287
+ window.open(`/canteen/generate_spreadsheet/${month}`, '_blank');
288
+ });
289
+
290
+ }
291
+
292
+ function submit_consumptions(fn) {
293
+ if (dont_submit) {
294
+ return false
295
+ } else {
296
+ dont_submit = true
297
+ }
298
+
299
+ var consumption_forms = $('form[name="consumption_form"]')
300
+ var requests = [];
301
+ var progress = 0
302
+ consumption_forms_cp = []
303
+ consumption_forms.each(function(index, element) {
304
+ var form = $(element);
305
+ var amount_used_init = parseInt(form.data("amount_used")) || 0
306
+ var amount_used_new = parseInt(form.find("input[name='amount_used']").val()) || 0
307
+ if (form.data("is_disabled") == "True") {
308
+ return true;
309
+ }
310
+ if (form.find('input[name="amount_used"]').val().length < 1) {
311
+ return true;
312
+ }
313
+ if (amount_used_new == amount_used_init) {
314
+ return true;
315
+ }
316
+ consumption_forms_cp.push(form)
317
+ });
318
+
319
+ consumption_forms = consumption_forms_cp
320
+ var consumption_forms_length = consumption_forms.length
321
+ $(consumption_forms).each(function(index, element) {
322
+ form = $(element)
323
+ requests.push(
324
+ $.ajax({
325
+ url: form.attr('action'),
326
+ type: form.attr('method') || 'POST',
327
+ data: form.serialize(),
328
+ success: function(response) {
329
+ progress += 1
330
+ var footer_progressbar = $('.progress-footer')
331
+ if (footer_progressbar) {
332
+ var width = `${parseInt(progress*100/consumption_forms_length)}%`
333
+ $(footer_progressbar).css("width", width)
334
+ }
335
+ }
336
+ }).catch(function(error) {
337
+ return erroe;
338
+ }));
339
+ });
340
+ $.when.apply($, requests)
341
+ .done(function() {
342
+ if (fn != undefined) {
343
+ fn()
344
+ }
345
+ location.reload();
346
+ })
347
+ .fail(function() {});
348
+ }
349
+
350
+ function set_consumptions_table_size() {
351
+ const submit_consumptions_btn = $(".btn-submit-consumptions")
352
+ const consumptions_table = $(".table-consumptions")
353
+ const header = $("header")
354
+ const footer = $("footer")
355
+ const height = Math.round((footer.offset().top - submit_consumptions_btn.height() - consumptions_table.offset().top) * 0.95)
356
+ consumptions_table.parent().height(height)
357
+ }
358
+ $(window).resize(function() {
359
+ set_consumptions_table_size()
360
+ });
361
+ $(document).ready(function() {
362
+ set_consumptions_table_size()
363
+ });
364
+
365
+ function list_consumptions() {
366
+ var storage_date_start = $('#storage_date_start').val()
367
+ var storage_date_end = $('#storage_date_end').val()
368
+ query = {}
369
+ if (storage_date_start) {
370
+ query["storage_date_start"] = storage_date_start
371
+ set_simple_cookie("storage_date_start", storage_date_start)
372
+ } else {
373
+ query["storage_date_start"] = ""
374
+ delete_cookie("storage_date_start")
375
+ }
376
+
377
+ if (storage_date_end) {
378
+ query["storage_date_end"] = storage_date_end
379
+ set_simple_cookie("storage_date_end", storage_date_end)
380
+ } else {
381
+ query["storage_date_end"] = ""
382
+ delete_cookie("storage_date_end")
383
+ }
384
+ update_href(query)
385
+ }
386
+ </script>
387
+ <style>
388
+ .ingredient-progress {
389
+ height: 2px;
390
+ background: green;
391
+ right: 9px;
392
+ position: absolute;
393
+ }
394
+
395
+ #storage_date_start,
396
+ #storage_date_end {
397
+ text-align: center;
398
+ font-family: Mono;
399
+ }
400
+
401
+ .weekend {
402
+ background-color: pink;
403
+ }
404
+
405
+ .table-container {
406
+ overflow: auto;
407
+ }
408
+
409
+ .table thead th {
410
+ position: -webkit-sticky;
411
+ position: sticky;
412
+ top: 0;
413
+ z-index: 1010;
414
+ white-space: nowrap;
415
+ }
416
+
417
+ .table tr {
418
+ font-size: 15px;
419
+ }
420
+
421
+ .table tr> :nth-child(1) {
422
+ position: -webkit-sticky;
423
+ position: sticky;
424
+ left: 0;
425
+ z-index: 1010;
426
+ white-space: nowrap;
427
+ text-align: right;
428
+ }
429
+
430
+ .table tr> :nth-child(2) {
431
+ position: -webkit-sticky;
432
+ position: sticky;
433
+ z-index: 1010;
434
+ font-family: Mono;
435
+ text-align: right;
436
+ }
437
+
438
+ .table thead tr {
439
+ font-size: 15px;
440
+ font-family: Mono;
441
+ }
442
+
443
+ .table thead tr> :nth-child(1) {
444
+ z-index: 1020;
445
+ white-space: nowrap;
446
+ }
447
+
448
+ .table thead tr> :nth-child(2) {
449
+ z-index: 1020;
450
+ }
451
+
452
+ nav li {
453
+ z-index: 1030;
454
+ }
455
+ </style>
456
+ {% endblock %}
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <body>
4
+ <script>
5
+ if (window.opener && !window.opener.closed) {
6
+ window.opener.location.reload();
7
+ }
8
+ window.close();
9
+ </script>
10
+ </body>
11
+ </html>
@@ -0,0 +1,19 @@
1
+ {% extends "base/content.html" %}
2
+ {% load crispy_forms_tags %}
3
+ {% block title %}
4
+ {% trans "Upload a Spreadsheet of Purchased Ingredients" %}
5
+ {% endblock %}
6
+ {% block content %}
7
+ <h2>{% trans "Please upload a spreadsheet of purchased ingredients." %}</h2>
8
+ <p>
9
+ {% trans "Need a template file?" %}
10
+ <a href="{% url 'canteen:get_template_workbook_of_purchased_ingredients' %}">{% trans "Download it." %}</a>
11
+ </p>
12
+ <form method="post" enctype="multipart/form-data">
13
+ {% csrf_token %} {{ form|crispy }}
14
+ <div class="py-3 fixed-bottom text-end bg-dark">
15
+ <button type="submit button" class="btn btn-outline-primary">{% trans "Upload" %}</button>
16
+ <button type="button" class="btn btn-danger" onclick="window.close();">{% trans "Cancel" %}</button>
17
+ </div>
18
+ </form>
19
+ {% endblock %}
@@ -0,0 +1,17 @@
1
+ {% extends "base/content.html" %}
2
+ {% load i18n %}
3
+ {% load crispy_forms_tags %}
4
+ {% block title %}
5
+ {% trans "New Ingredient" %}
6
+ {% endblock %}
7
+ {% block content %}
8
+ <h1>{% trans "Create new Ingredient" %}</h1>
9
+ <form method="post" action="{% url 'canteen:create_ingredient' %}">
10
+ {% csrf_token %}
11
+ {{ form|crispy }}
12
+ <div class="py-3 fixed-bottom text-end bg-dark">
13
+ <button type="submit" class="btn btn-primary">{% trans "Save" %}</button>
14
+ <button type="button" class="btn btn-danger" onclick="window.close();">{% trans "Cancel" %}</button>
15
+ </div>
16
+ </form>
17
+ {% endblock %}
@@ -0,0 +1,41 @@
1
+ {% extends "base/content.html" %}
2
+ {% load crispy_forms_tags %}
3
+ {% block title %}
4
+ {% blocktrans with instance_name=form.instance.name %}
5
+ Delete Ingredient {{ instance_name }}
6
+ {% endblocktrans %}
7
+ {% endblock %}
8
+ {% block content %}
9
+ <h5 class="">
10
+ {% blocktrans with instance_name=form.instance.name%}
11
+ Delete Ingredient {{ instance_name }} .
12
+ {% endblocktrans %}
13
+ </h5>
14
+ <p>
15
+ <dl>
16
+ {% for field in form %}
17
+ <dt>{{ field.label }}</dt>
18
+ <dd>
19
+ {{ field.value }}
20
+ </dd>
21
+ {% endfor %}
22
+ </dl>
23
+ </p>
24
+ <p class="text-danger">
25
+ {% blocktrans %}
26
+ Are you sure you want to delete this ingredient? This operation is irreversible.
27
+ {% endblocktrans%}
28
+ </p>
29
+ <div class="py-3 fixed-bottom text-end bg-dark">
30
+ <form method="post"
31
+ action="{% url 'canteen:delete_ingredient' form.instance.pk %}"
32
+ style="display: inline">
33
+ {% csrf_token %}
34
+ <button type="submit" class="btn btn-danger">{% trans 'Delete' %}</button>
35
+ <button type="button" class="btn btn-primary" onclick="window.close();">{% trans "Cancel" %}</button>
36
+ </form>
37
+ </div>
38
+ <script>
39
+ localize_content($("dd"))
40
+ </script>
41
+ {% endblock %}
@@ -0,0 +1,128 @@
1
+ {% extends "base/header_content_footer.html" %}
2
+ {% load crispy_forms_tags %}
3
+ {% block title %}
4
+ {% trans "Ingredient List" %}
5
+ {% endblock %}
6
+ {% block content %}
7
+ <h1>{% trans "Ingredient List" %}</h1>
8
+ <form method="get"
9
+ action="{% url 'canteen:list_ingredients' %}"
10
+ class="d-flex justify-content-between align-items-center">
11
+ <input type="text"
12
+ name="q"
13
+ onkeydown="if(event.keyCode==13){submit_q();return false;}"
14
+ value="{{ search_query }}"
15
+ placeholder="{% trans 'Search ingredient ...' %}"
16
+ class="form-control" />
17
+ <button type="button"
18
+ onclick="submit_q();"
19
+ class="btn btn-primary text-nowrap">{% trans "Search" %}</button>
20
+ {% if search_query %}
21
+ <a onclick="clear_q();" class="text-nowrap">{% trans "Clear" %}</a>
22
+ {% endif %}
23
+ </form>
24
+ <div class="d-flex justify-content-end pt-2">
25
+ <a class="btn btn-primary mx-1"
26
+ href="{% url "canteen:list_meal_types" %}">{% trans "Ingredient Meal Types" %}</a>
27
+ <a class="btn btn-primary mx-1"
28
+ href="{% url "canteen:list_categories" %}">{% trans "Ingredient Categories" %}</a>
29
+ <a class="btn btn-warning mx-1"
30
+ href="{% url "canteen:create_consumptions" %}">{% trans "Consume" %}</a>
31
+ <a class="btn btn-primary mx-1"
32
+ onclick="open_small_window('{% url 'canteen:create_ingredients' %}')">{% trans "Add via template" %}</a>
33
+ <a class="btn btn-primary"
34
+ onclick="open_small_window('{% url 'canteen:create_ingredient' %}')">{% trans "Add one" %}</a>
35
+ </div>
36
+ <hr />
37
+ <table class="table table-bordered table-striped table-hover table-condensed">
38
+ <thead>
39
+ <tr>
40
+ <th scope="col">#</th>
41
+ {% for name,sort, header in headers %}
42
+ <th scope="col"
43
+ data-sort="sort_{{ name }} {{ sort }}"
44
+ onclick="sort_ingredients(this.dataset.sort);">
45
+ {{ header }}
46
+ {% if sort == "+" %}
47
+ &#8593;
48
+ {% elif sort == "-" %}
49
+ &#8595;
50
+ {% endif %}
51
+ </th>
52
+ {% endfor %}
53
+ <th scope="col"></th>
54
+ </tr>
55
+ </thead>
56
+ <tbody>
57
+ {% for ingredient in page_obj %}
58
+ <tr>
59
+ <th scope="row">{{ forloop.counter }}</th>
60
+ <td>{{ ingredient.storage_date }}</td>
61
+ <td>{{ ingredient.name }}</td>
62
+ <td>{{ ingredient.meal_type }}</td>
63
+ <td>{{ ingredient.category }}</td>
64
+ <td>{{ ingredient.quantity }}</td>
65
+ <td>{{ ingredient.quantity_unit_name }}</td>
66
+ <td>{{ ingredient.total_price }}</td>
67
+ <td>
68
+ {% if ingredient.is_ignorable %}
69
+ {% trans "Yes" %}
70
+ {% endif %}
71
+ </td>
72
+ <td>
73
+ {% if ingredient.is_disabled %}
74
+ {% trans "Yes" %}
75
+ {% endif %}
76
+ </td>
77
+ <td class="">
78
+ <a class=""
79
+ target="_blank"
80
+ onclick="open_small_window('{% url 'canteen:edit_ingredient' ingredient.id %}'); return false;">
81
+ {% trans "Edit" %}
82
+ </a>
83
+ |
84
+ <a class="text-danger"
85
+ target="_blank"
86
+ onclick="open_small_window('{% url 'canteen:delete_ingredient' ingredient.id %}'); return false;">
87
+ {% trans "Delete" %}
88
+ </a>
89
+ </td>
90
+ </tr>
91
+ {% empty %}
92
+ {% endfor %}
93
+ </tbody>
94
+ </table>
95
+ {% include 'includes/_paginator.html' %}
96
+ <script>
97
+ function clear_q() {
98
+ update_href({
99
+ "q": ""
100
+ })
101
+ }
102
+
103
+ function submit_q() {
104
+ const q_value = document.querySelector('input[name="q"]').value;
105
+ update_href({
106
+ q: q_value
107
+ });
108
+ }
109
+
110
+ function sort_ingredients(value) {
111
+ value = value.trim().split(/\s+/);
112
+ name = value[0];
113
+ value = value[1] || "";
114
+ const url = new URL(window.location.href);
115
+ const params = new URLSearchParams(url.search);
116
+ if (value == "-") {
117
+ value = "";
118
+ } else if (value == "") {
119
+ value = "+";
120
+ } else {
121
+ value = "-";
122
+ }
123
+ i_sort = {};
124
+ i_sort[name] = value;
125
+ update_href(i_sort);
126
+ }
127
+ </script>
128
+ {% endblock %}