aa-ledger 1.0.4__py3-none-any.whl → 2.0.0__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.
Files changed (280) hide show
  1. {aa_ledger-1.0.4.dist-info → aa_ledger-2.0.0.dist-info}/METADATA +5 -6
  2. aa_ledger-2.0.0.dist-info/RECORD +267 -0
  3. ledger/__init__.py +2 -2
  4. ledger/admin.py +23 -18
  5. ledger/api/__init__.py +23 -7
  6. ledger/api/{ledger/admin.py → admin.py} +25 -31
  7. ledger/api/alliance.py +755 -0
  8. ledger/api/character.py +786 -0
  9. ledger/api/corporation.py +1141 -0
  10. ledger/api/{helpers.py → helpers/core.py} +33 -33
  11. ledger/api/helpers/icons.py +372 -0
  12. ledger/api/helpers/planetary_helper.py +354 -0
  13. ledger/api/planetary.py +354 -0
  14. ledger/api/schema.py +240 -15
  15. ledger/app_settings.py +11 -27
  16. ledger/auth_hooks.py +2 -2
  17. ledger/constants.py +50 -177
  18. ledger/decorators.py +2 -46
  19. ledger/forms.py +133 -39
  20. ledger/helpers/billboard.py +194 -144
  21. ledger/helpers/cache.py +105 -0
  22. ledger/helpers/discord.py +2 -4
  23. ledger/helpers/eveonline.py +160 -0
  24. ledger/helpers/ledger_data.py +23 -0
  25. ledger/helpers/ref_type.py +53 -78
  26. ledger/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  27. ledger/locale/cs_CZ/LC_MESSAGES/django.po +349 -193
  28. ledger/locale/de/LC_MESSAGES/django.mo +0 -0
  29. ledger/locale/de/LC_MESSAGES/django.po +528 -379
  30. ledger/locale/django.pot +721 -546
  31. ledger/locale/es/LC_MESSAGES/django.mo +0 -0
  32. ledger/locale/es/LC_MESSAGES/django.po +349 -194
  33. ledger/locale/fr_FR/LC_MESSAGES/django.mo +0 -0
  34. ledger/locale/fr_FR/LC_MESSAGES/django.po +349 -193
  35. ledger/locale/it_IT/LC_MESSAGES/django.mo +0 -0
  36. ledger/locale/it_IT/LC_MESSAGES/django.po +349 -193
  37. ledger/locale/ja/LC_MESSAGES/django.mo +0 -0
  38. ledger/locale/ja/LC_MESSAGES/django.po +348 -193
  39. ledger/locale/ko_KR/LC_MESSAGES/django.mo +0 -0
  40. ledger/locale/ko_KR/LC_MESSAGES/django.po +349 -193
  41. ledger/locale/nl_NL/LC_MESSAGES/django.mo +0 -0
  42. ledger/locale/nl_NL/LC_MESSAGES/django.po +349 -193
  43. ledger/locale/pl_PL/LC_MESSAGES/django.mo +0 -0
  44. ledger/locale/pl_PL/LC_MESSAGES/django.po +350 -193
  45. ledger/locale/ru/LC_MESSAGES/django.mo +0 -0
  46. ledger/locale/ru/LC_MESSAGES/django.po +348 -193
  47. ledger/locale/sk/LC_MESSAGES/django.mo +0 -0
  48. ledger/locale/sk/LC_MESSAGES/django.po +348 -193
  49. ledger/locale/uk/LC_MESSAGES/django.mo +0 -0
  50. ledger/locale/uk/LC_MESSAGES/django.po +348 -193
  51. ledger/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  52. ledger/locale/zh_Hans/LC_MESSAGES/django.po +348 -193
  53. ledger/managers/character_audit_manager.py +28 -20
  54. ledger/managers/character_journal_manager.py +185 -357
  55. ledger/managers/character_mining_manager.py +52 -26
  56. ledger/managers/character_planetary_manager.py +178 -136
  57. ledger/managers/corporation_audit_manager.py +36 -27
  58. ledger/managers/corporation_journal_manager.py +92 -56
  59. ledger/managers/general_manager.py +8 -7
  60. ledger/migrations/0018_remove_characterplanet_ledger_char_planet__58a5b6_idx_and_more.py +44 -0
  61. ledger/migrations/0019_rename_characteraudit_characterowner_and_more.py +48 -0
  62. ledger/models/__init__.py +5 -11
  63. ledger/models/characteraudit.py +101 -109
  64. ledger/models/corporationaudit.py +94 -49
  65. ledger/models/general.py +105 -211
  66. ledger/models/helpers/update_manager.py +302 -0
  67. ledger/models/planetary.py +60 -205
  68. ledger/providers.py +101 -0
  69. ledger/static/ledger/css/{ledger.css → aa-ledger.css} +54 -28
  70. ledger/static/ledger/js/aa-ledger.js +124 -0
  71. ledger/static/ledger/js/charts.js +25 -1
  72. ledger/static/ledger/js/view-alliance-ledger.js +383 -0
  73. ledger/static/ledger/js/view-character-ledger.js +388 -0
  74. ledger/static/ledger/js/view-corporation-ledger.js +402 -0
  75. ledger/static/ledger/js/view-planetary.js +492 -0
  76. ledger/static/ledger/libs/amCharts/5.14.4/js/flow.js +2 -0
  77. ledger/static/ledger/libs/amCharts/5.14.4/js/index.js +2 -0
  78. ledger/static/ledger/libs/amCharts/5.14.4/js/percent.js +2 -0
  79. ledger/static/ledger/libs/amCharts/5.14.4/js/themes/Animated.js +2 -0
  80. ledger/static/ledger/libs/amCharts/5.14.4/js/themes/Dark.js +2 -0
  81. ledger/static/ledger/libs/amCharts/5.14.4/js/xy.js +2 -0
  82. ledger/static/ledger/libs/datatables/2.3.5/css/dataTables.bootstrap5.css +610 -0
  83. ledger/static/ledger/libs/datatables/2.3.5/js/dataTables.bootstrap5.js +122 -0
  84. ledger/static/ledger/libs/datatables/2.3.5/js/dataTables.js +14127 -0
  85. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/css/columnControl.bootstrap5.css +516 -0
  86. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/css/columnControl.dataTables.css +529 -0
  87. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/js/columnControl.bootstrap5.js +73 -0
  88. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/js/dataTables.columnControl.js +3090 -0
  89. ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/css/fixedHeader.bootstrap5.css +20 -0
  90. ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/js/dataTables.fixedHeader.js +1203 -0
  91. ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/js/fixedHeader.bootstrap5.js +59 -0
  92. ledger/tasks.py +157 -141
  93. ledger/templates/ledger/base.html +59 -21
  94. ledger/templates/ledger/bundles/aa-ledger-css.html +3 -0
  95. ledger/templates/ledger/bundles/aa-ledger-js.html +3 -0
  96. ledger/templates/ledger/bundles/view-alliance-ledger-js.html +14 -0
  97. ledger/templates/ledger/bundles/view-character-ledger-js.html +15 -0
  98. ledger/templates/ledger/bundles/view-character-planetary-css.html +3 -0
  99. ledger/templates/ledger/bundles/view-character-planetary-js.html +4 -0
  100. ledger/templates/ledger/bundles/view-corporation-ledger-js.html +15 -0
  101. ledger/templates/ledger/partials/modal/confirm.html +0 -1
  102. ledger/templates/ledger/partials/modal/request-accept-delete-alliance.html +38 -0
  103. ledger/templates/ledger/partials/modal/request-accept-delete-character.html +38 -0
  104. ledger/templates/ledger/partials/modal/request-accept-delete-corporation.html +38 -0
  105. ledger/templates/ledger/partials/modal/request-accept-switch-notification.html +38 -0
  106. ledger/templates/ledger/partials/modal/request-view-alliance-details.html +26 -0
  107. ledger/templates/ledger/partials/modal/request-view-character-details.html +26 -0
  108. ledger/templates/ledger/partials/modal/request-view-corporation-details.html +26 -0
  109. ledger/templates/ledger/partials/modal/request-view-extractor.html +32 -0
  110. ledger/templates/ledger/partials/modal/request-view-factory.html +31 -0
  111. ledger/templates/ledger/partials/{menu → navigation}/administration.html +8 -0
  112. ledger/templates/ledger/partials/{menu → navigation}/navigation.html +2 -2
  113. ledger/templates/ledger/partials/{administration → view-alliance-administration}/alliance_corporations.html +3 -3
  114. ledger/templates/ledger/partials/view-alliance-administration/dashboard.html +81 -0
  115. ledger/templates/ledger/partials/view-alliance-ledger/alliance-billboard.html +25 -0
  116. ledger/templates/ledger/partials/view-alliance-ledger/alliance-ledger-details.html +21 -0
  117. ledger/templates/ledger/partials/view-alliance-ledger/alliance-table.html +24 -0
  118. ledger/templates/ledger/partials/view-alliance-ledger/information/daily.html +18 -0
  119. ledger/templates/ledger/partials/view-alliance-ledger/information/hourly.html +18 -0
  120. ledger/templates/ledger/partials/view-alliance-ledger/information/summary.html +19 -0
  121. ledger/templates/ledger/partials/{administration → view-character-administration}/character.html +1 -9
  122. ledger/templates/ledger/partials/{administration → view-character-administration}/dashboard.html +0 -34
  123. ledger/templates/ledger/partials/view-character-ledger/character-billboard.html +25 -0
  124. ledger/templates/ledger/partials/view-character-ledger/character-ledger-details.html +21 -0
  125. ledger/templates/ledger/partials/view-character-ledger/character-table.html +25 -0
  126. ledger/templates/ledger/partials/view-character-ledger/information/daily.html +18 -0
  127. ledger/templates/ledger/partials/view-character-ledger/information/hourly.html +18 -0
  128. ledger/templates/ledger/partials/view-character-ledger/information/summary.html +19 -0
  129. ledger/templates/ledger/partials/view-character-planetary/extractor-table.html +24 -0
  130. ledger/templates/ledger/partials/view-character-planetary/factory-table.html +24 -0
  131. ledger/templates/ledger/partials/view-character-planetary/planetary-table.html +22 -0
  132. ledger/templates/ledger/partials/view-character-planetary/storage-table.html +23 -0
  133. ledger/templates/ledger/partials/{administration → view-corporation-administration}/corporation.html +5 -13
  134. ledger/templates/ledger/partials/{administration → view-corporation-administration}/corporation_characters.html +1 -1
  135. ledger/templates/ledger/partials/view-corporation-administration/dashboard.html +81 -0
  136. ledger/templates/ledger/partials/view-corporation-ledger/corporation-billboard.html +25 -0
  137. ledger/templates/ledger/partials/view-corporation-ledger/corporation-ledger-details.html +21 -0
  138. ledger/templates/ledger/partials/view-corporation-ledger/corporation-table.html +26 -0
  139. ledger/templates/ledger/partials/view-corporation-ledger/information/daily.html +18 -0
  140. ledger/templates/ledger/partials/view-corporation-ledger/information/hourly.html +18 -0
  141. ledger/templates/ledger/partials/view-corporation-ledger/information/summary.html +19 -0
  142. ledger/templates/ledger/view-administration.html +62 -0
  143. ledger/templates/ledger/view-alliance-administration.html +49 -0
  144. ledger/templates/ledger/view-alliance-ledger.html +72 -0
  145. ledger/templates/ledger/view-alliance-overview.html +131 -0
  146. ledger/templates/ledger/view-character-administration.html +42 -0
  147. ledger/templates/ledger/view-character-ledger.html +73 -0
  148. ledger/templates/ledger/view-character-overview.html +135 -0
  149. ledger/templates/ledger/view-character-planetary-overview.html +135 -0
  150. ledger/templates/ledger/view-character-planetary.html +73 -0
  151. ledger/templates/ledger/view-corporation-administration.html +42 -0
  152. ledger/templates/ledger/view-corporation-ledger.html +73 -0
  153. ledger/templates/ledger/view-corporation-overview.html +131 -0
  154. ledger/templatetags/ledger.py +3 -5
  155. ledger/tests/__init__.py +187 -0
  156. ledger/tests/test_admin.py +164 -68
  157. ledger/tests/test_auth_hook.py +31 -13
  158. ledger/tests/test_decarators.py +14 -79
  159. ledger/tests/test_discord_installed.py +0 -1
  160. ledger/tests/test_helpers/test_ledger_data.py +19 -0
  161. ledger/tests/test_managers/test_character_audit_manager.py +111 -69
  162. ledger/tests/test_managers/test_character_journal_manager.py +48 -208
  163. ledger/tests/test_managers/test_character_mining_manager.py +37 -16
  164. ledger/tests/test_managers/test_corporation_division_manager.py +66 -28
  165. ledger/tests/test_managers/test_corporation_journal_manager.py +39 -42
  166. ledger/tests/test_managers/test_general_manager.py +78 -18
  167. ledger/tests/test_managers/test_planetary_manager.py +73 -32
  168. ledger/tests/test_models/test_characteraudit.py +58 -74
  169. ledger/tests/test_models/test_characterminingledger.py +20 -26
  170. ledger/tests/test_models/test_characterwalletjournal.py +10 -33
  171. ledger/tests/test_models/test_corporationaudit.py +41 -35
  172. ledger/tests/test_models/test_corporationwalletjournal.py +35 -32
  173. ledger/tests/test_models/test_general.py +44 -11
  174. ledger/tests/test_models/test_planetary.py +14 -80
  175. ledger/tests/test_templatetags.py +2 -7
  176. ledger/tests/test_views/corporation/test_add_corp.py +16 -35
  177. ledger/tests/test_views/corporation/test_delete_corporation.py +66 -42
  178. ledger/tests/test_views/test_access.py +512 -545
  179. ledger/tests/test_views/test_add_ally.py +57 -46
  180. ledger/tests/test_views/test_add_char.py +21 -33
  181. ledger/tests/test_views/test_delete_character.py +24 -21
  182. ledger/tests/testdata/README_ESI_STUB.md +430 -0
  183. ledger/tests/testdata/esi_stub_openapi.py +511 -0
  184. ledger/tests/testdata/integrations/__init__.py +0 -0
  185. ledger/tests/testdata/{load_eveuniverse.py → integrations/eveuniverse.py} +0 -1
  186. ledger/tests/testdata/integrations/planetary.py +13 -0
  187. ledger/tests/testdata/json/factory.json +281 -0
  188. ledger/tests/testdata/json/inactive.json +281 -0
  189. ledger/tests/testdata/json/pins.json +175 -272
  190. ledger/tests/testdata/json/route.json +95 -528
  191. ledger/tests/testdata/test_esi_stub.py +468 -0
  192. ledger/tests/testdata/utils.py +601 -0
  193. ledger/thirdparty/charlink_hook.py +60 -30
  194. ledger/urls.py +0 -135
  195. ledger/views/alliance/add_ally.py +2 -4
  196. ledger/views/alliance/alliance_ledger.py +64 -147
  197. ledger/views/character/add_char.py +8 -10
  198. ledger/views/character/character_ledger.py +60 -126
  199. ledger/views/character/planetary.py +5 -98
  200. ledger/views/corporation/add_corp.py +10 -12
  201. ledger/views/corporation/corporation_ledger.py +65 -327
  202. ledger/views/index.py +92 -30
  203. aa_ledger-1.0.4.dist-info/RECORD +0 -236
  204. ledger/api/api_helper/planetary_helper.py +0 -107
  205. ledger/api/ledger/__init__.py +0 -7
  206. ledger/api/ledger/planetary.py +0 -231
  207. ledger/helpers/alliance.py +0 -317
  208. ledger/helpers/character.py +0 -251
  209. ledger/helpers/core.py +0 -665
  210. ledger/helpers/corporation.py +0 -427
  211. ledger/helpers/data_exporter.py +0 -452
  212. ledger/static/ledger/js/planetary-confirm.js +0 -66
  213. ledger/static/ledger/js/planetary.js +0 -143
  214. ledger/templates/ledger/admin.html +0 -43
  215. ledger/templates/ledger/allyledger/admin/alliance_administration.html +0 -46
  216. ledger/templates/ledger/allyledger/admin/alliance_overview.html +0 -108
  217. ledger/templates/ledger/allyledger/alliance_ledger.html +0 -86
  218. ledger/templates/ledger/bundles/character-ledger-bundles.html +0 -66
  219. ledger/templates/ledger/bundles/corporation-ledger-bundles.html +0 -75
  220. ledger/templates/ledger/bundles/ledger-bundles.html +0 -23
  221. ledger/templates/ledger/bundles/ledger-css.html +0 -3
  222. ledger/templates/ledger/bundles/planetary-bundles.html +0 -50
  223. ledger/templates/ledger/bundles/table-css.html +0 -3
  224. ledger/templates/ledger/charledger/admin/character_administration.html +0 -39
  225. ledger/templates/ledger/charledger/admin/character_overview.html +0 -106
  226. ledger/templates/ledger/charledger/character_ledger.html +0 -94
  227. ledger/templates/ledger/charledger/planetary/admin/planetary_overview.html +0 -123
  228. ledger/templates/ledger/charledger/planetary/planetary_ledger.html +0 -54
  229. ledger/templates/ledger/corpledger/admin/corporation_administration.html +0 -39
  230. ledger/templates/ledger/corpledger/admin/corporation_overview.html +0 -108
  231. ledger/templates/ledger/corpledger/corporation_ledger.html +0 -129
  232. ledger/templates/ledger/data-export.html +0 -78
  233. ledger/templates/ledger/error.html +0 -31
  234. ledger/templates/ledger/partials/form/error-message.html +0 -1
  235. ledger/templates/ledger/partials/information/daily.html +0 -56
  236. ledger/templates/ledger/partials/information/day.html +0 -48
  237. ledger/templates/ledger/partials/information/error.html +0 -8
  238. ledger/templates/ledger/partials/information/hourly.html +0 -53
  239. ledger/templates/ledger/partials/information/summary.html +0 -88
  240. ledger/templates/ledger/partials/information/view_character_content.html +0 -35
  241. ledger/templates/ledger/partials/modal/switchalarm_confirm.html +0 -39
  242. ledger/templates/ledger/partials/modal/view_extractor.html +0 -48
  243. ledger/templates/ledger/partials/modal/view_factory.html +0 -123
  244. ledger/templates/ledger/partials/table/char-ledger.html +0 -85
  245. ledger/templates/ledger/partials/table/corp-ledger.html +0 -66
  246. ledger/templates/ledger/partials/table/planetary.html +0 -18
  247. ledger/templates/ledger/partials/thirdparty/billboard.html +0 -22
  248. ledger/templates/ledger/partials/view/card.html +0 -160
  249. ledger/templates/ledger/permission.html +0 -2
  250. ledger/tests/test_helpers/test_billboard.py +0 -11
  251. ledger/tests/test_helpers/test_data_exporter.py +0 -207
  252. ledger/tests/test_tasks.py +0 -282
  253. ledger/tests/test_view_helpers/test_core.py +0 -47
  254. ledger/tests/test_views/corporation/test_corporation.py +0 -267
  255. ledger/tests/test_views/test_planetary.py +0 -137
  256. ledger/tests/testdata/esi_stub.py +0 -109
  257. ledger/tests/testdata/esi_stub_migration.py +0 -80
  258. ledger/tests/testdata/generate_characteraudit.py +0 -106
  259. ledger/tests/testdata/generate_corporationaudit.py +0 -74
  260. ledger/tests/testdata/generate_events.py +0 -31
  261. ledger/tests/testdata/generate_miningledger.py +0 -13
  262. ledger/tests/testdata/generate_planets.py +0 -48
  263. ledger/tests/testdata/generate_walletjournal.py +0 -42
  264. ledger/tests/testdata/json/czarno-pins.json +0 -240
  265. ledger/tests/testdata/json/czarno-routes.json +0 -165
  266. ledger/tests/testdata/json/pins2.json +0 -538
  267. {aa_ledger-1.0.4.dist-info → aa_ledger-2.0.0.dist-info}/WHEEL +0 -0
  268. {aa_ledger-1.0.4.dist-info → aa_ledger-2.0.0.dist-info}/licenses/LICENSE +0 -0
  269. /ledger/{tests/test_view_helpers → api/helpers}/__init__.py +0 -0
  270. /ledger/templates/ledger/bundles/{ally-administration-bundles.html → view-alliance-administration-js.html} +0 -0
  271. /ledger/templates/ledger/bundles/{char-administration-bundles.html → view-character-administration-js.html} +0 -0
  272. /ledger/templates/ledger/bundles/{corp-administration-bundles.html → view-corporation-administration-js.html} +0 -0
  273. /ledger/templates/ledger/partials/{administration → view-alliance-administration}/alliance.html +0 -0
  274. /ledger/tests/testdata/{esi.json → esi_test_data.json} +0 -0
  275. /ledger/tests/testdata/{allianceauth.json → integrations/allianceauth.json} +0 -0
  276. /ledger/tests/testdata/{load_allianceauth.py → integrations/allianceauth.py} +0 -0
  277. /ledger/tests/testdata/{eveentity.json → integrations/eveentity.json} +0 -0
  278. /ledger/tests/testdata/{load_eveentity.py → integrations/eveentity.py} +0 -0
  279. /ledger/tests/testdata/{eveuniverse.json → integrations/eveuniverse.json} +0 -0
  280. /ledger/tests/testdata/{planetary.json → integrations/planetary.json} +0 -0
ledger/api/alliance.py ADDED
@@ -0,0 +1,755 @@
1
+ # Standard Library
2
+ from decimal import Decimal
3
+
4
+ # Third Party
5
+ from ninja import NinjaAPI, Schema
6
+
7
+ # Django
8
+ from django.contrib.humanize.templatetags.humanize import intcomma
9
+ from django.core.handlers.wsgi import WSGIRequest
10
+ from django.db.models import Q, QuerySet
11
+ from django.utils import timezone
12
+ from django.utils.translation import gettext as _
13
+
14
+ # Alliance Auth
15
+ from allianceauth.eveonline.models import EveAllianceInfo
16
+ from allianceauth.services.hooks import get_extension_logger
17
+
18
+ # AA Ledger
19
+ from ledger import __title__
20
+ from ledger.api.helpers.core import (
21
+ get_alliance_or_none,
22
+ )
23
+ from ledger.api.helpers.icons import (
24
+ get_alliance_details_info_button,
25
+ get_ref_type_details_popover_button,
26
+ )
27
+ from ledger.api.schema import (
28
+ AllianceLedgerRequestInfo,
29
+ BillboardSchema,
30
+ CategorySchema,
31
+ EntitySchema,
32
+ LedgerDetailsResponse,
33
+ LedgerDetailsSummary,
34
+ LedgerResponse,
35
+ LedgerSchema,
36
+ OwnerSchema,
37
+ UpdateStatusSchema,
38
+ )
39
+ from ledger.helpers.billboard import BillboardSystem
40
+ from ledger.helpers.cache import CacheManager
41
+ from ledger.helpers.eveonline import get_alliance_logo_url, get_corporation_logo_url
42
+ from ledger.helpers.ledger_data import get_footer_text_class
43
+ from ledger.helpers.ref_type import RefTypeManager
44
+ from ledger.models.corporationaudit import (
45
+ CorporationOwner,
46
+ CorporationWalletJournalEntry,
47
+ )
48
+ from ledger.providers import AppLogger
49
+
50
+ logger = AppLogger(get_extension_logger(__name__), __title__)
51
+
52
+
53
+ class LedgerAllianceSchema(Schema):
54
+ corporation: EntitySchema
55
+ ledger: LedgerSchema
56
+ update_status: UpdateStatusSchema | None = None
57
+ actions: str = ""
58
+
59
+
60
+ class AllianceLedgerResponse(LedgerResponse):
61
+ """
62
+ Schema for Alliance Ledger API Response
63
+
64
+ This schema represents the structure of the response returned by the Alliance Ledger API.
65
+ extending the base :class:`LedgerResponse` to include alliance-specific data.
66
+
67
+ Attributes:
68
+ information (AllianceLedgerRequestInfo): Information about the alliance ledger request.
69
+ corporations (list[LedgerAllianceSchema]): A list of ledger entities associated with the alliance.
70
+ """
71
+
72
+ information: AllianceLedgerRequestInfo
73
+ corporations: list[LedgerAllianceSchema]
74
+
75
+
76
+ class AllianceApiEndpoints:
77
+ tags = ["Alliance"]
78
+
79
+ # pylint: disable=too-many-statements, function-redefined, duplicate-code
80
+ # flake8: noqa: F811
81
+ def __init__(self, api: NinjaAPI):
82
+ self.cache_manager = CacheManager()
83
+ self.billboard = BillboardSystem()
84
+
85
+ @api.get(
86
+ "alliance/{alliance_id}/date/{year}/",
87
+ response={200: AllianceLedgerResponse, 403: dict, 404: dict},
88
+ tags=self.tags,
89
+ )
90
+ def get_alliance_ledger(request: WSGIRequest, alliance_id: int, year: int):
91
+ """Get the ledger for a character for a specific year. Admin Endpoint."""
92
+ return self._ledger_api_response(
93
+ request=request,
94
+ alliance_id=alliance_id,
95
+ year=year,
96
+ )
97
+
98
+ @api.get(
99
+ "alliance/{alliance_id}/date/{year}/{month}/",
100
+ response={200: AllianceLedgerResponse, 403: dict, 404: dict},
101
+ tags=self.tags,
102
+ )
103
+ def get_alliance_ledger(
104
+ request: WSGIRequest, alliance_id: int, year: int, month: int
105
+ ):
106
+ """Get the ledger for a character for a specific year. Admin Endpoint."""
107
+ return self._ledger_api_response(
108
+ request=request,
109
+ alliance_id=alliance_id,
110
+ year=year,
111
+ month=month,
112
+ )
113
+
114
+ @api.get(
115
+ "alliance/{alliance_id}/date/{year}/{month}/{day}/",
116
+ response={200: AllianceLedgerResponse, 403: dict, 404: dict},
117
+ tags=self.tags,
118
+ )
119
+ def get_alliance_ledger(
120
+ request: WSGIRequest,
121
+ alliance_id: int,
122
+ year: int,
123
+ month: int,
124
+ day: int,
125
+ ):
126
+ """Get the ledger for a character for a specific year. Admin Endpoint."""
127
+ return self._ledger_api_response(
128
+ request=request,
129
+ alliance_id=alliance_id,
130
+ year=year,
131
+ month=month,
132
+ day=day,
133
+ )
134
+
135
+ # pylint: disable=duplicate-code
136
+ def _create_datatable_footer(
137
+ self,
138
+ corporations: list[LedgerAllianceSchema],
139
+ request_info: AllianceLedgerRequestInfo,
140
+ ) -> AllianceLedgerRequestInfo:
141
+ """
142
+ Create the footer HTML for the Ledger datatable.
143
+
144
+ This Helper function creates the footer HTML for the Ledger datatable
145
+ by summing up the respective fields from the list of corporations.
146
+
147
+ Args:
148
+ corporations (list[LedgerAllianceSchema]): The list of corporation ledger data.
149
+ request_info (AllianceLedgerRequestInfo): The request information object.
150
+ Returns:
151
+ str: The generated footer HTML.
152
+ """
153
+ total_bounty = sum(entity.ledger.bounty for entity in corporations)
154
+ total_ess = sum(entity.ledger.ess for entity in corporations)
155
+ total_costs = sum(entity.ledger.costs for entity in corporations)
156
+ total_miscellaneous = sum(
157
+ entity.ledger.miscellaneous for entity in corporations
158
+ )
159
+ total_total = sum(entity.ledger.total for entity in corporations)
160
+
161
+ # Generate Details Link
162
+ url = get_alliance_details_info_button(
163
+ entity_id=request_info.owner_id,
164
+ request_info=request_info,
165
+ )
166
+
167
+ # Skip Footer if no Totals
168
+ if total_total == 0:
169
+ return ""
170
+
171
+ footer_html = f"""
172
+ <tr>
173
+ <th class="border-top">{_("Summary")}</th>
174
+ <th class="border-top text-end {get_footer_text_class(total_bounty)}">{intcomma(value=int(total_bounty), use_l10n=True)} ISK</th>
175
+ <th class="border-top text-end {get_footer_text_class(total_ess)}">{intcomma(value=int(total_ess), use_l10n=True)} ISK</th>
176
+ <th class="border-top text-end {get_footer_text_class(total_miscellaneous)}">{intcomma(value=int(total_miscellaneous), use_l10n=True)} ISK</th>
177
+ <th class="border-top text-end {get_footer_text_class(total_costs)}">{intcomma(value=int(total_costs), use_l10n=True)} ISK</th>
178
+ <th class="border-start border-top text-end {get_footer_text_class(total_total)}">{intcomma(value=int(total_total), use_l10n=True)} ISK</th>
179
+ <th class="border-top">{url}</th>
180
+ </tr>
181
+ """
182
+ request_info.footer_html = footer_html
183
+ return request_info
184
+
185
+ def generate_corporation_data(
186
+ self,
187
+ owner: EveAllianceInfo,
188
+ request_info: AllianceLedgerRequestInfo,
189
+ ):
190
+ """
191
+ Generate the corporation ledger data for the alliance.
192
+
193
+ This Helper function generates the corporation ledger data for all corporation of the Alliance
194
+ based on the provided request information.
195
+
196
+ Args:
197
+ owner (EveAllianceInfo): The alliance owner object.
198
+ request_info (AllianceLedgerRequestInfo): The request information object.
199
+ Returns:
200
+ list[LedgerAllianceSchema]: The generated alliance ledger data.
201
+
202
+ """
203
+ corporations = CorporationOwner.objects.filter(
204
+ eve_corporation__alliance__alliance_id=owner.alliance_id
205
+ )
206
+
207
+ alliance_ledger_list: list[LedgerAllianceSchema] = []
208
+ for corporation in corporations:
209
+ wallet_journal = (
210
+ CorporationWalletJournalEntry.objects.filter(
211
+ division__corporation=corporation,
212
+ **request_info.to_date_query(),
213
+ )
214
+ # Exclude Zero Amount Entries
215
+ .exclude(amount=Decimal("0.00"))
216
+ # Exclude Internal Transfers
217
+ .exclude(
218
+ first_party_id=corporation.eve_corporation.corporation_id,
219
+ second_party_id=corporation.eve_corporation.corporation_id,
220
+ )
221
+ )
222
+
223
+ if not wallet_journal.exists():
224
+ continue
225
+
226
+ # Get IDs for Hashing
227
+ header_ids = list(wallet_journal.values_list("entry_id", flat=True))
228
+
229
+ # Add Alliance ID to header ids to ensure uniqueness
230
+ header_ids.append(owner.alliance_id)
231
+
232
+ # Create Ledger Hash
233
+ wallet_journal_hash = self.cache_manager.create_ledger_hash(header_ids)
234
+
235
+ # Get Cached Ledger if Available
236
+ response_ledger = self.cache_manager.get_cache_key(
237
+ ledger_hash=wallet_journal_hash, key="alliance"
238
+ )
239
+ if response_ledger is False:
240
+ logger.debug(f"Ledger Cache Miss for: {corporation}")
241
+
242
+ # Aggregate Data
243
+ bounty = wallet_journal.aggregate_bounty()
244
+ ess = wallet_journal.aggregate_ess()
245
+ miscellaneous = wallet_journal.aggregate_miscellaneous()
246
+ costs = wallet_journal.aggregate_costs()
247
+
248
+ total = sum(
249
+ [
250
+ bounty,
251
+ ess,
252
+ miscellaneous,
253
+ costs,
254
+ ]
255
+ )
256
+
257
+ response_ledger = LedgerAllianceSchema(
258
+ corporation=EntitySchema(
259
+ entity_id=corporation.eve_corporation.corporation_id,
260
+ entity_name=corporation.eve_corporation.corporation_name,
261
+ icon=get_corporation_logo_url(
262
+ corporation_id=corporation.eve_corporation.corporation_id,
263
+ corporation_name=corporation.eve_corporation.corporation_name,
264
+ as_html=True,
265
+ ),
266
+ ),
267
+ ledger=LedgerSchema(
268
+ bounty=bounty,
269
+ ess=ess,
270
+ miscellaneous=miscellaneous,
271
+ costs=costs,
272
+ total=total,
273
+ ),
274
+ update_status=UpdateStatusSchema(
275
+ status=corporation.get_status,
276
+ ),
277
+ actions=get_alliance_details_info_button(
278
+ entity_id=corporation.eve_corporation.corporation_id,
279
+ request_info=request_info,
280
+ ),
281
+ )
282
+ # Cache Ledger Response
283
+ self.cache_manager.set_cache_key(
284
+ key="alliance",
285
+ ledger_hash=wallet_journal_hash,
286
+ ledger_data=response_ledger,
287
+ )
288
+
289
+ # Add to Corporation Ledger List
290
+ alliance_ledger_list.append(response_ledger)
291
+ return alliance_ledger_list
292
+
293
+ # pylint: disable=too-many-locals
294
+ def generate_billboard_data(
295
+ self,
296
+ owner: EveAllianceInfo,
297
+ alliance_ledger_list: list[LedgerAllianceSchema],
298
+ request_info: AllianceLedgerRequestInfo,
299
+ ) -> BillboardSchema:
300
+ """
301
+ Generate the billboard data for the corporation ledger.
302
+
303
+ This Helper function generates the billboard data for the corporation
304
+ based on the provided alliance ledger data.
305
+
306
+ Args:
307
+ owner (CorporationOwner): The corporation owner object.
308
+ alliance_ledger_list (list[LedgerAllianceSchema]): The list of alliance ledger data.
309
+ request_info (LedgerRequestInfo): The request information object.
310
+ Returns:
311
+ BillboardSchema: The generated billboard data.
312
+ """
313
+ corporations = CorporationOwner.objects.filter(
314
+ eve_corporation__alliance__alliance_id=owner.alliance_id
315
+ )
316
+
317
+ # Get Wallet Journal Entries
318
+ corp_wallet_journal = (
319
+ CorporationWalletJournalEntry.objects.filter(
320
+ division__corporation__in=corporations,
321
+ **request_info.to_date_query(),
322
+ )
323
+ # Exclude Zero Amount Entries
324
+ .exclude(amount=Decimal("0.00"))
325
+ # Exclude Internal Transfers
326
+ .exclude(
327
+ Q(
328
+ first_party_id__in=[
329
+ corp.eve_corporation.corporation_id for corp in corporations
330
+ ]
331
+ )
332
+ & Q(
333
+ second_party_id__in=[
334
+ corp.eve_corporation.corporation_id for corp in corporations
335
+ ]
336
+ )
337
+ )
338
+ )
339
+
340
+ # Get IDs for Hashing
341
+ header_ids = list(corp_wallet_journal.values_list("entry_id", flat=True))
342
+
343
+ # Skip Alliance if no Ledger Entries
344
+ if len(header_ids) == 0:
345
+ return BillboardSchema()
346
+
347
+ # Add Alliance ID to header ids to ensure uniqueness
348
+ header_ids.append(owner.alliance_id)
349
+
350
+ # Create Ledger Hash
351
+ wallet_journal_hash = self.cache_manager.create_ledger_hash(header_ids)
352
+
353
+ # Get Cached Billboard if Available
354
+ response_billboard = self.cache_manager.get_cache_key(
355
+ key="alliance-billboard", ledger_hash=wallet_journal_hash
356
+ )
357
+
358
+ if response_billboard is False:
359
+ logger.debug(f"Billboard Cache for: {owner}")
360
+ # Create Timelines
361
+ wallet_timeline = (
362
+ self.billboard.create_timeline(
363
+ journal=corp_wallet_journal, request_info=request_info
364
+ )
365
+ .annotate_bounty_income()
366
+ .annotate_ess_income()
367
+ .annotate_miscellaneous()
368
+ )
369
+
370
+ # Generate XY Billboard
371
+ xy_results = self.billboard.create_or_update_results(wallet_timeline)
372
+ xy_billboard = self.billboard.create_xy_billboard(
373
+ results=xy_results, request_info=request_info
374
+ )
375
+ # Initialize Chord Billboard
376
+ chord_billboard = self.billboard.create_chord_billboard(
377
+ alliance_ledger_list
378
+ )
379
+
380
+ response_billboard = BillboardSchema(
381
+ xy_chart=xy_billboard, chord_chart=chord_billboard
382
+ )
383
+ # Cache Billboard Response
384
+ self.cache_manager.set_cache_key(
385
+ key="alliance-billboard",
386
+ ledger_hash=wallet_journal_hash,
387
+ ledger_data=response_billboard,
388
+ )
389
+ # Billboard Data Generation Logic Here
390
+ return response_billboard
391
+
392
+ # pylint: disable=duplicate-code
393
+ def _ledger_api_response(
394
+ self,
395
+ request,
396
+ alliance_id: int,
397
+ year: int,
398
+ month: int = None,
399
+ day: int = None,
400
+ ) -> AllianceLedgerResponse | tuple[int, dict]:
401
+ """
402
+ Helper function to generate ledger response for various date parameters.
403
+
404
+ This function consolidates the common logic for generating the ledger response
405
+ based on the provided date parameters (year, month, day).
406
+
407
+ Args:
408
+ request (WSGIRequest): The incoming request object.
409
+ alliance_id (int): The alliance ID.
410
+ year (int): The year for the ledger data.
411
+ month (int, optional): The month for the ledger data. Defaults to None.
412
+ day (int, optional): The day for the ledger data. Defaults to None.
413
+
414
+ Returns:
415
+ AllianceLedgerResponse | tuple[int, dict]: The ledger response or error tuple.
416
+ """
417
+ perms, owner = get_alliance_or_none(request=request, alliance_id=alliance_id)
418
+
419
+ if owner is None:
420
+ return 404, {"error": _("Alliance not found in Ledger.")}
421
+
422
+ if perms is False:
423
+ return 403, {
424
+ "error": _("You do not have permission to view this alliance.")
425
+ }
426
+
427
+ # Build Request Info
428
+ request_info = AllianceLedgerRequestInfo(
429
+ owner_id=owner.alliance_id,
430
+ year=year,
431
+ month=month,
432
+ day=day,
433
+ )
434
+
435
+ # Generate Corporation Ledger Data
436
+ corporation_ledger_list = self.generate_corporation_data(
437
+ owner=owner,
438
+ request_info=request_info,
439
+ )
440
+
441
+ # Generate Billboard Data
442
+ billboard = self.generate_billboard_data(
443
+ owner=owner,
444
+ alliance_ledger_list=corporation_ledger_list,
445
+ request_info=request_info,
446
+ )
447
+
448
+ # Update Request Info with Available Data
449
+ self._create_datatable_footer(
450
+ corporations=corporation_ledger_list, request_info=request_info
451
+ )
452
+
453
+ response_ledger = AllianceLedgerResponse(
454
+ owner=OwnerSchema(
455
+ character_id=owner.alliance_id,
456
+ character_name=owner.alliance_name,
457
+ icon=get_alliance_logo_url(
458
+ alliance_id=owner.alliance_id,
459
+ alliance_name=owner.alliance_name,
460
+ as_html=True,
461
+ ),
462
+ ),
463
+ information=request_info,
464
+ corporations=corporation_ledger_list,
465
+ billboard=billboard,
466
+ actions=get_alliance_details_info_button(
467
+ entity_id=owner.alliance_id,
468
+ request_info=request_info,
469
+ ),
470
+ )
471
+
472
+ return response_ledger
473
+
474
+
475
+ class AllianceDetailsApiEndpoints:
476
+ tags = ["Alliance Details"]
477
+
478
+ # pylint: disable=too-many-statements, function-redefined, too-many-arguments, duplicate-code
479
+ def __init__(self, api: NinjaAPI):
480
+ @api.get(
481
+ "alliance/{alliance_id}/date/{year}/section/{section}/view/details/{entity_id}/",
482
+ response={200: LedgerDetailsResponse, 403: dict, 404: dict},
483
+ tags=self.tags,
484
+ )
485
+ def get_alliance_ledger_details(
486
+ request: WSGIRequest,
487
+ alliance_id: int,
488
+ year: int,
489
+ section: str,
490
+ entity_id: int,
491
+ ):
492
+ return self._ledger_details_api_response(
493
+ request=request,
494
+ alliance_id=alliance_id,
495
+ entity_id=entity_id,
496
+ year=year,
497
+ section=section,
498
+ )
499
+
500
+ @api.get(
501
+ "alliance/{alliance_id}/date/{year}/{month}/section/{section}/view/details/{entity_id}/",
502
+ response={200: LedgerDetailsResponse, 403: dict, 404: dict},
503
+ tags=self.tags,
504
+ )
505
+ def get_alliance_ledger_details(
506
+ request: WSGIRequest,
507
+ alliance_id: int,
508
+ year: int,
509
+ month: int,
510
+ section: str,
511
+ entity_id: int,
512
+ ):
513
+ return self._ledger_details_api_response(
514
+ request=request,
515
+ alliance_id=alliance_id,
516
+ entity_id=entity_id,
517
+ year=year,
518
+ month=month,
519
+ section=section,
520
+ )
521
+
522
+ @api.get(
523
+ "alliance/{alliance_id}/date/{year}/{month}/{day}/section/{section}/view/details/{entity_id}/",
524
+ response={200: LedgerDetailsResponse, 403: dict, 404: dict},
525
+ tags=self.tags,
526
+ )
527
+ # pylint: disable=too-many-positional-arguments
528
+ def get_alliance_ledger_details(
529
+ request: WSGIRequest,
530
+ alliance_id: int,
531
+ year: int,
532
+ month: int,
533
+ day: int,
534
+ section: str,
535
+ entity_id: int,
536
+ ):
537
+ return self._ledger_details_api_response(
538
+ request=request,
539
+ alliance_id=alliance_id,
540
+ entity_id=entity_id,
541
+ year=year,
542
+ month=month,
543
+ day=day,
544
+ section=section,
545
+ )
546
+
547
+ # pylint: disable=duplicate-code
548
+ def _create_datatable_footer(self, value: float) -> str:
549
+ """Create the footer HTML for the datatable."""
550
+ footer_html = f"""
551
+ <tr>
552
+ <th>{_('Summary')}</th>
553
+ <th class="text-end {get_footer_text_class(value)}">{intcomma(value=int(value), use_l10n=True)} ISK</th>
554
+ <th></th>
555
+ </tr>
556
+ """
557
+ return footer_html
558
+
559
+ # pylint: disable=too-many-locals
560
+ def _create_ledger_details(
561
+ self,
562
+ journal: QuerySet[CorporationWalletJournalEntry],
563
+ request_info: AllianceLedgerRequestInfo,
564
+ ) -> LedgerDetailsResponse:
565
+ """
566
+ Generate the detailed ledger data for a character.
567
+ This Helper function generates the detailed ledger data for a character
568
+ based on the provided date query.
569
+
570
+ Args:
571
+ journal (QuerySet): The wallet journal entries.
572
+ mining (QuerySet): The mining ledger entries. Defaults to None.
573
+ request_info (LedgerRequestInfo): The request information containing date and section details.
574
+ Returns:
575
+ LedgerDetailsResponse: The generated ledger details response.
576
+ """
577
+ ref_types = RefTypeManager.get_all_categories()
578
+
579
+ avg = request_info.day if request_info.day else timezone.now().day
580
+ if request_info.section == "summary":
581
+ avg = 365
582
+
583
+ monthly_list = []
584
+ daily_list = []
585
+ hourly_list = []
586
+ summary = 0
587
+ # Income/Cost Ref Types
588
+ for category in RefTypeManager.CategoryChoice:
589
+ category_ref_types = ref_types.get(category.value, [])
590
+ if not category_ref_types:
591
+ continue
592
+ for __, income_flag in (("income", True), ("cost", False)):
593
+ kind_label = _("Income from") if income_flag else _("Cost from")
594
+ name = _("%(kind)s %(category)s") % {
595
+ "category": category.label,
596
+ "kind": kind_label,
597
+ }
598
+ kwargs = {"ref_type": category_ref_types, "income": income_flag}
599
+ amount = journal.aggregate_ref_type(**kwargs)
600
+ if (income_flag and amount > 0) or (not income_flag and amount < 0):
601
+ monthly = CategorySchema(
602
+ name=name,
603
+ amount=amount,
604
+ average=amount / avg / 30,
605
+ average_tick=amount / avg / 30 / 20,
606
+ ref_types=get_ref_type_details_popover_button(
607
+ ref_types=category_ref_types
608
+ ),
609
+ )
610
+
611
+ daily = CategorySchema(
612
+ name=name,
613
+ amount=amount / avg,
614
+ average=amount / avg / 30,
615
+ average_tick=amount / avg / 20,
616
+ ref_types=get_ref_type_details_popover_button(
617
+ ref_types=category_ref_types
618
+ ),
619
+ )
620
+
621
+ hourly = CategorySchema(
622
+ name=name,
623
+ amount=amount / avg / 24,
624
+ average=amount / avg / 24 / 30,
625
+ average_tick=amount / avg / 24 / 20,
626
+ ref_types=get_ref_type_details_popover_button(
627
+ ref_types=category_ref_types
628
+ ),
629
+ )
630
+ # Add Amounts
631
+ summary += amount
632
+ monthly_list.append(monthly)
633
+ daily_list.append(daily)
634
+ hourly_list.append(hourly)
635
+
636
+ if summary == 0:
637
+ return None
638
+
639
+ return LedgerDetailsResponse(
640
+ summary=monthly_list,
641
+ daily=daily_list,
642
+ hourly=hourly_list,
643
+ total=LedgerDetailsSummary(
644
+ summary=self._create_datatable_footer(summary),
645
+ daily=self._create_datatable_footer(
646
+ summary / avg,
647
+ ),
648
+ hourly=self._create_datatable_footer(
649
+ summary / avg / 24,
650
+ ),
651
+ ),
652
+ )
653
+
654
+ def create_entity_details(
655
+ self,
656
+ owner: EveAllianceInfo,
657
+ entity_id: int,
658
+ request_info: AllianceLedgerRequestInfo,
659
+ ) -> dict:
660
+ """
661
+ Create the entity amounts for the Information View.
662
+ """
663
+ # Get Division Query
664
+ if owner.alliance_id == entity_id:
665
+ corporation_ids = list(
666
+ CorporationOwner.objects.filter(
667
+ eve_corporation__alliance__alliance_id=owner.alliance_id
668
+ ).values_list("eve_corporation__corporation_id", flat=True)
669
+ )
670
+ division_query = Q(
671
+ division__corporation__eve_corporation__alliance__alliance_id=owner.alliance_id
672
+ )
673
+ exclude_query = None
674
+ if corporation_ids:
675
+ exclude_query = Q(first_party_id__in=corporation_ids) & Q(
676
+ second_party_id__in=corporation_ids
677
+ )
678
+ else:
679
+ exclude_query = Q(first_party_id=entity_id, second_party_id=entity_id)
680
+ division_query = Q(
681
+ division__corporation__eve_corporation__corporation_id=entity_id
682
+ )
683
+
684
+ # Get Wallet Journal Entries
685
+ wallet_journal = (
686
+ CorporationWalletJournalEntry.objects.filter(
687
+ division_query,
688
+ **request_info.to_date_query(),
689
+ )
690
+ # Exclude Zero Amount Entries
691
+ .exclude(amount=Decimal("0.00"))
692
+ )
693
+
694
+ # Exclude Internal Transfers only when we have a meaningful exclude_query
695
+ if exclude_query is not None:
696
+ wallet_journal = wallet_journal.exclude(exclude_query)
697
+
698
+ response_ledger_details: LedgerDetailsResponse = self._create_ledger_details(
699
+ journal=wallet_journal,
700
+ request_info=request_info,
701
+ )
702
+ return response_ledger_details
703
+
704
+ # pylint: disable=too-many-arguments, too-many-positional-arguments
705
+ def _ledger_details_api_response(
706
+ self,
707
+ request: WSGIRequest,
708
+ alliance_id: int,
709
+ entity_id: int,
710
+ year: int,
711
+ month: int = None,
712
+ day: int = None,
713
+ section: str = "summary",
714
+ ):
715
+ """
716
+ Helper function to generate ledger details response for various date parameters.
717
+
718
+ This function consolidates the common logic for generating the ledger details response
719
+ based on the provided date parameters character_id, (year, month, day) and section.
720
+
721
+ Args:
722
+ request (WSGIRequest): The incoming request object.
723
+ alliance_id (int): The alliance ID.
724
+ entity_id (int): The entity ID.
725
+ year (int): The year for the ledger data.
726
+ month (int, optional): The month for the ledger data. Defaults to None.
727
+ day (int, optional): The day for the ledger data. Defaults to None.
728
+ section (str): The section type ('single' or 'summary').
729
+ Returns:
730
+ LedgerDetailsResponse | tuple[int, dict]: The ledger details response or error tuple.
731
+ """
732
+ perms, owner = get_alliance_or_none(request=request, alliance_id=alliance_id)
733
+
734
+ if owner is None:
735
+ return 404, {"error": _("Alliance not found in Ledger.")}
736
+
737
+ if perms is False:
738
+ return 403, {
739
+ "error": _("You do not have permission to view this alliance.")
740
+ }
741
+
742
+ request_info = AllianceLedgerRequestInfo(
743
+ owner_id=owner.alliance_id,
744
+ entity_id=entity_id,
745
+ year=year,
746
+ month=month,
747
+ day=day,
748
+ section=section,
749
+ )
750
+
751
+ return self.create_entity_details(
752
+ owner=owner,
753
+ entity_id=entity_id,
754
+ request_info=request_info,
755
+ )