aa-ledger 1.0.3__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.3.dist-info → aa_ledger-2.0.0.dist-info}/METADATA +6 -6
  2. aa_ledger-2.0.0.dist-info/RECORD +267 -0
  3. {aa_ledger-1.0.3.dist-info → aa_ledger-2.0.0.dist-info}/WHEEL +1 -1
  4. ledger/__init__.py +2 -2
  5. ledger/admin.py +23 -18
  6. ledger/api/__init__.py +23 -7
  7. ledger/api/{ledger/admin.py → admin.py} +25 -31
  8. ledger/api/alliance.py +755 -0
  9. ledger/api/character.py +786 -0
  10. ledger/api/corporation.py +1141 -0
  11. ledger/api/{helpers.py → helpers/core.py} +33 -33
  12. ledger/api/helpers/icons.py +372 -0
  13. ledger/api/helpers/planetary_helper.py +354 -0
  14. ledger/api/planetary.py +354 -0
  15. ledger/api/schema.py +240 -15
  16. ledger/app_settings.py +18 -26
  17. ledger/auth_hooks.py +2 -2
  18. ledger/constants.py +50 -177
  19. ledger/decorators.py +2 -46
  20. ledger/forms.py +133 -39
  21. ledger/helpers/billboard.py +194 -144
  22. ledger/helpers/cache.py +105 -0
  23. ledger/helpers/discord.py +2 -4
  24. ledger/helpers/eveonline.py +160 -0
  25. ledger/helpers/ledger_data.py +23 -0
  26. ledger/helpers/ref_type.py +53 -78
  27. ledger/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  28. ledger/locale/cs_CZ/LC_MESSAGES/django.po +349 -193
  29. ledger/locale/de/LC_MESSAGES/django.mo +0 -0
  30. ledger/locale/de/LC_MESSAGES/django.po +528 -379
  31. ledger/locale/django.pot +717 -553
  32. ledger/locale/es/LC_MESSAGES/django.mo +0 -0
  33. ledger/locale/es/LC_MESSAGES/django.po +349 -194
  34. ledger/locale/fr_FR/LC_MESSAGES/django.mo +0 -0
  35. ledger/locale/fr_FR/LC_MESSAGES/django.po +349 -193
  36. ledger/locale/it_IT/LC_MESSAGES/django.mo +0 -0
  37. ledger/locale/it_IT/LC_MESSAGES/django.po +349 -193
  38. ledger/locale/ja/LC_MESSAGES/django.mo +0 -0
  39. ledger/locale/ja/LC_MESSAGES/django.po +348 -193
  40. ledger/locale/ko_KR/LC_MESSAGES/django.mo +0 -0
  41. ledger/locale/ko_KR/LC_MESSAGES/django.po +349 -193
  42. ledger/locale/nl_NL/LC_MESSAGES/django.mo +0 -0
  43. ledger/locale/nl_NL/LC_MESSAGES/django.po +349 -193
  44. ledger/locale/pl_PL/LC_MESSAGES/django.mo +0 -0
  45. ledger/locale/pl_PL/LC_MESSAGES/django.po +350 -193
  46. ledger/locale/ru/LC_MESSAGES/django.mo +0 -0
  47. ledger/locale/ru/LC_MESSAGES/django.po +348 -193
  48. ledger/locale/sk/LC_MESSAGES/django.mo +0 -0
  49. ledger/locale/sk/LC_MESSAGES/django.po +348 -193
  50. ledger/locale/uk/LC_MESSAGES/django.mo +0 -0
  51. ledger/locale/uk/LC_MESSAGES/django.po +348 -193
  52. ledger/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  53. ledger/locale/zh_Hans/LC_MESSAGES/django.po +348 -193
  54. ledger/managers/character_audit_manager.py +28 -20
  55. ledger/managers/character_journal_manager.py +187 -358
  56. ledger/managers/character_mining_manager.py +64 -30
  57. ledger/managers/character_planetary_manager.py +185 -138
  58. ledger/managers/corporation_audit_manager.py +36 -27
  59. ledger/managers/corporation_journal_manager.py +94 -57
  60. ledger/managers/general_manager.py +12 -8
  61. ledger/migrations/0018_remove_characterplanet_ledger_char_planet__58a5b6_idx_and_more.py +44 -0
  62. ledger/migrations/0019_rename_characteraudit_characterowner_and_more.py +48 -0
  63. ledger/models/__init__.py +5 -11
  64. ledger/models/characteraudit.py +101 -109
  65. ledger/models/corporationaudit.py +94 -49
  66. ledger/models/general.py +105 -211
  67. ledger/models/helpers/update_manager.py +302 -0
  68. ledger/models/planetary.py +60 -205
  69. ledger/providers.py +101 -0
  70. ledger/static/ledger/css/{ledger.css → aa-ledger.css} +54 -28
  71. ledger/static/ledger/js/aa-ledger.js +124 -0
  72. ledger/static/ledger/js/charts.js +25 -1
  73. ledger/static/ledger/js/view-alliance-ledger.js +383 -0
  74. ledger/static/ledger/js/view-character-ledger.js +388 -0
  75. ledger/static/ledger/js/view-corporation-ledger.js +402 -0
  76. ledger/static/ledger/js/view-planetary.js +492 -0
  77. ledger/static/ledger/libs/amCharts/5.14.4/js/flow.js +2 -0
  78. ledger/static/ledger/libs/amCharts/5.14.4/js/index.js +2 -0
  79. ledger/static/ledger/libs/amCharts/5.14.4/js/percent.js +2 -0
  80. ledger/static/ledger/libs/amCharts/5.14.4/js/themes/Animated.js +2 -0
  81. ledger/static/ledger/libs/amCharts/5.14.4/js/themes/Dark.js +2 -0
  82. ledger/static/ledger/libs/amCharts/5.14.4/js/xy.js +2 -0
  83. ledger/static/ledger/libs/datatables/2.3.5/css/dataTables.bootstrap5.css +610 -0
  84. ledger/static/ledger/libs/datatables/2.3.5/js/dataTables.bootstrap5.js +122 -0
  85. ledger/static/ledger/libs/datatables/2.3.5/js/dataTables.js +14127 -0
  86. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/css/columnControl.bootstrap5.css +516 -0
  87. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/css/columnControl.dataTables.css +529 -0
  88. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/js/columnControl.bootstrap5.js +73 -0
  89. ledger/static/ledger/libs/datatables/Extensions/ColumnControl/1.1.1/js/dataTables.columnControl.js +3090 -0
  90. ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/css/fixedHeader.bootstrap5.css +20 -0
  91. ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/js/dataTables.fixedHeader.js +1203 -0
  92. ledger/static/ledger/libs/datatables/Extensions/FixedHeader/4.0.4/js/fixedHeader.bootstrap5.js +59 -0
  93. ledger/tasks.py +157 -146
  94. ledger/templates/ledger/base.html +59 -21
  95. ledger/templates/ledger/bundles/aa-ledger-css.html +3 -0
  96. ledger/templates/ledger/bundles/aa-ledger-js.html +3 -0
  97. ledger/templates/ledger/bundles/view-alliance-ledger-js.html +14 -0
  98. ledger/templates/ledger/bundles/view-character-ledger-js.html +15 -0
  99. ledger/templates/ledger/bundles/view-character-planetary-css.html +3 -0
  100. ledger/templates/ledger/bundles/view-character-planetary-js.html +4 -0
  101. ledger/templates/ledger/bundles/view-corporation-ledger-js.html +15 -0
  102. ledger/templates/ledger/partials/modal/confirm.html +0 -1
  103. ledger/templates/ledger/partials/modal/request-accept-delete-alliance.html +38 -0
  104. ledger/templates/ledger/partials/modal/request-accept-delete-character.html +38 -0
  105. ledger/templates/ledger/partials/modal/request-accept-delete-corporation.html +38 -0
  106. ledger/templates/ledger/partials/modal/request-accept-switch-notification.html +38 -0
  107. ledger/templates/ledger/partials/modal/request-view-alliance-details.html +26 -0
  108. ledger/templates/ledger/partials/modal/request-view-character-details.html +26 -0
  109. ledger/templates/ledger/partials/modal/request-view-corporation-details.html +26 -0
  110. ledger/templates/ledger/partials/modal/request-view-extractor.html +32 -0
  111. ledger/templates/ledger/partials/modal/request-view-factory.html +31 -0
  112. ledger/templates/ledger/partials/{menu → navigation}/administration.html +8 -0
  113. ledger/templates/ledger/partials/{menu → navigation}/navigation.html +2 -2
  114. ledger/templates/ledger/partials/{administration → view-alliance-administration}/alliance_corporations.html +3 -3
  115. ledger/templates/ledger/partials/view-alliance-administration/dashboard.html +81 -0
  116. ledger/templates/ledger/partials/view-alliance-ledger/alliance-billboard.html +25 -0
  117. ledger/templates/ledger/partials/view-alliance-ledger/alliance-ledger-details.html +21 -0
  118. ledger/templates/ledger/partials/view-alliance-ledger/alliance-table.html +24 -0
  119. ledger/templates/ledger/partials/view-alliance-ledger/information/daily.html +18 -0
  120. ledger/templates/ledger/partials/view-alliance-ledger/information/hourly.html +18 -0
  121. ledger/templates/ledger/partials/view-alliance-ledger/information/summary.html +19 -0
  122. ledger/templates/ledger/partials/{administration → view-character-administration}/character.html +1 -9
  123. ledger/templates/ledger/partials/{administration → view-character-administration}/dashboard.html +0 -34
  124. ledger/templates/ledger/partials/view-character-ledger/character-billboard.html +25 -0
  125. ledger/templates/ledger/partials/view-character-ledger/character-ledger-details.html +21 -0
  126. ledger/templates/ledger/partials/view-character-ledger/character-table.html +25 -0
  127. ledger/templates/ledger/partials/view-character-ledger/information/daily.html +18 -0
  128. ledger/templates/ledger/partials/view-character-ledger/information/hourly.html +18 -0
  129. ledger/templates/ledger/partials/view-character-ledger/information/summary.html +19 -0
  130. ledger/templates/ledger/partials/view-character-planetary/extractor-table.html +24 -0
  131. ledger/templates/ledger/partials/view-character-planetary/factory-table.html +24 -0
  132. ledger/templates/ledger/partials/view-character-planetary/planetary-table.html +22 -0
  133. ledger/templates/ledger/partials/view-character-planetary/storage-table.html +23 -0
  134. ledger/templates/ledger/partials/{administration → view-corporation-administration}/corporation.html +5 -13
  135. ledger/templates/ledger/partials/{administration → view-corporation-administration}/corporation_characters.html +1 -1
  136. ledger/templates/ledger/partials/view-corporation-administration/dashboard.html +81 -0
  137. ledger/templates/ledger/partials/view-corporation-ledger/corporation-billboard.html +25 -0
  138. ledger/templates/ledger/partials/view-corporation-ledger/corporation-ledger-details.html +21 -0
  139. ledger/templates/ledger/partials/view-corporation-ledger/corporation-table.html +26 -0
  140. ledger/templates/ledger/partials/view-corporation-ledger/information/daily.html +18 -0
  141. ledger/templates/ledger/partials/view-corporation-ledger/information/hourly.html +18 -0
  142. ledger/templates/ledger/partials/view-corporation-ledger/information/summary.html +19 -0
  143. ledger/templates/ledger/view-administration.html +62 -0
  144. ledger/templates/ledger/view-alliance-administration.html +49 -0
  145. ledger/templates/ledger/view-alliance-ledger.html +72 -0
  146. ledger/templates/ledger/view-alliance-overview.html +131 -0
  147. ledger/templates/ledger/view-character-administration.html +42 -0
  148. ledger/templates/ledger/view-character-ledger.html +73 -0
  149. ledger/templates/ledger/view-character-overview.html +135 -0
  150. ledger/templates/ledger/view-character-planetary-overview.html +135 -0
  151. ledger/templates/ledger/view-character-planetary.html +73 -0
  152. ledger/templates/ledger/view-corporation-administration.html +42 -0
  153. ledger/templates/ledger/view-corporation-ledger.html +73 -0
  154. ledger/templates/ledger/view-corporation-overview.html +131 -0
  155. ledger/templatetags/ledger.py +3 -5
  156. ledger/tests/__init__.py +187 -0
  157. ledger/tests/test_admin.py +164 -68
  158. ledger/tests/test_auth_hook.py +31 -13
  159. ledger/tests/test_decarators.py +14 -79
  160. ledger/tests/test_discord_installed.py +0 -1
  161. ledger/tests/test_helpers/test_ledger_data.py +19 -0
  162. ledger/tests/test_managers/test_character_audit_manager.py +111 -69
  163. ledger/tests/test_managers/test_character_journal_manager.py +48 -208
  164. ledger/tests/test_managers/test_character_mining_manager.py +37 -16
  165. ledger/tests/test_managers/test_corporation_division_manager.py +66 -28
  166. ledger/tests/test_managers/test_corporation_journal_manager.py +39 -42
  167. ledger/tests/test_managers/test_general_manager.py +78 -18
  168. ledger/tests/test_managers/test_planetary_manager.py +73 -32
  169. ledger/tests/test_models/test_characteraudit.py +58 -74
  170. ledger/tests/test_models/test_characterminingledger.py +20 -26
  171. ledger/tests/test_models/test_characterwalletjournal.py +10 -33
  172. ledger/tests/test_models/test_corporationaudit.py +41 -35
  173. ledger/tests/test_models/test_corporationwalletjournal.py +35 -32
  174. ledger/tests/test_models/test_general.py +44 -11
  175. ledger/tests/test_models/test_planetary.py +14 -80
  176. ledger/tests/test_templatetags.py +2 -7
  177. ledger/tests/test_views/corporation/test_add_corp.py +16 -35
  178. ledger/tests/test_views/corporation/test_delete_corporation.py +66 -42
  179. ledger/tests/test_views/test_access.py +512 -545
  180. ledger/tests/test_views/test_add_ally.py +57 -46
  181. ledger/tests/test_views/test_add_char.py +21 -33
  182. ledger/tests/test_views/test_delete_character.py +24 -21
  183. ledger/tests/testdata/README_ESI_STUB.md +430 -0
  184. ledger/tests/testdata/esi_stub_openapi.py +511 -0
  185. ledger/tests/testdata/integrations/__init__.py +0 -0
  186. ledger/tests/testdata/{load_eveuniverse.py → integrations/eveuniverse.py} +0 -1
  187. ledger/tests/testdata/integrations/planetary.py +13 -0
  188. ledger/tests/testdata/json/factory.json +281 -0
  189. ledger/tests/testdata/json/inactive.json +281 -0
  190. ledger/tests/testdata/json/pins.json +175 -272
  191. ledger/tests/testdata/json/route.json +95 -528
  192. ledger/tests/testdata/test_esi_stub.py +468 -0
  193. ledger/tests/testdata/utils.py +601 -0
  194. ledger/thirdparty/charlink_hook.py +60 -30
  195. ledger/urls.py +0 -135
  196. ledger/views/alliance/add_ally.py +2 -4
  197. ledger/views/alliance/alliance_ledger.py +64 -147
  198. ledger/views/character/add_char.py +8 -10
  199. ledger/views/character/character_ledger.py +60 -126
  200. ledger/views/character/planetary.py +5 -98
  201. ledger/views/corporation/add_corp.py +10 -12
  202. ledger/views/corporation/corporation_ledger.py +65 -327
  203. ledger/views/index.py +92 -30
  204. aa_ledger-1.0.3.dist-info/RECORD +0 -236
  205. ledger/api/api_helper/planetary_helper.py +0 -107
  206. ledger/api/ledger/__init__.py +0 -7
  207. ledger/api/ledger/planetary.py +0 -231
  208. ledger/helpers/alliance.py +0 -317
  209. ledger/helpers/character.py +0 -251
  210. ledger/helpers/core.py +0 -665
  211. ledger/helpers/corporation.py +0 -427
  212. ledger/helpers/data_exporter.py +0 -452
  213. ledger/static/ledger/js/planetary-confirm.js +0 -66
  214. ledger/static/ledger/js/planetary.js +0 -143
  215. ledger/templates/ledger/admin.html +0 -43
  216. ledger/templates/ledger/allyledger/admin/alliance_administration.html +0 -46
  217. ledger/templates/ledger/allyledger/admin/alliance_overview.html +0 -108
  218. ledger/templates/ledger/allyledger/alliance_ledger.html +0 -86
  219. ledger/templates/ledger/bundles/character-ledger-bundles.html +0 -66
  220. ledger/templates/ledger/bundles/corporation-ledger-bundles.html +0 -75
  221. ledger/templates/ledger/bundles/ledger-bundles.html +0 -23
  222. ledger/templates/ledger/bundles/ledger-css.html +0 -3
  223. ledger/templates/ledger/bundles/planetary-bundles.html +0 -50
  224. ledger/templates/ledger/bundles/table-css.html +0 -3
  225. ledger/templates/ledger/charledger/admin/character_administration.html +0 -39
  226. ledger/templates/ledger/charledger/admin/character_overview.html +0 -106
  227. ledger/templates/ledger/charledger/character_ledger.html +0 -94
  228. ledger/templates/ledger/charledger/planetary/admin/planetary_overview.html +0 -123
  229. ledger/templates/ledger/charledger/planetary/planetary_ledger.html +0 -54
  230. ledger/templates/ledger/corpledger/admin/corporation_administration.html +0 -39
  231. ledger/templates/ledger/corpledger/admin/corporation_overview.html +0 -108
  232. ledger/templates/ledger/corpledger/corporation_ledger.html +0 -129
  233. ledger/templates/ledger/data-export.html +0 -78
  234. ledger/templates/ledger/error.html +0 -31
  235. ledger/templates/ledger/partials/form/error-message.html +0 -1
  236. ledger/templates/ledger/partials/information/daily.html +0 -56
  237. ledger/templates/ledger/partials/information/day.html +0 -48
  238. ledger/templates/ledger/partials/information/error.html +0 -8
  239. ledger/templates/ledger/partials/information/hourly.html +0 -53
  240. ledger/templates/ledger/partials/information/summary.html +0 -88
  241. ledger/templates/ledger/partials/information/view_character_content.html +0 -35
  242. ledger/templates/ledger/partials/modal/switchalarm_confirm.html +0 -39
  243. ledger/templates/ledger/partials/modal/view_extractor.html +0 -48
  244. ledger/templates/ledger/partials/modal/view_factory.html +0 -123
  245. ledger/templates/ledger/partials/table/char-ledger.html +0 -85
  246. ledger/templates/ledger/partials/table/corp-ledger.html +0 -66
  247. ledger/templates/ledger/partials/table/planetary.html +0 -18
  248. ledger/templates/ledger/partials/thirdparty/billboard.html +0 -22
  249. ledger/templates/ledger/partials/view/card.html +0 -160
  250. ledger/templates/ledger/permission.html +0 -2
  251. ledger/tests/test_helpers/test_billboard.py +0 -11
  252. ledger/tests/test_helpers/test_data_exporter.py +0 -207
  253. ledger/tests/test_tasks.py +0 -282
  254. ledger/tests/test_view_helpers/test_core.py +0 -47
  255. ledger/tests/test_views/corporation/test_corporation.py +0 -267
  256. ledger/tests/test_views/test_planetary.py +0 -137
  257. ledger/tests/testdata/esi_stub.py +0 -109
  258. ledger/tests/testdata/esi_stub_migration.py +0 -80
  259. ledger/tests/testdata/generate_characteraudit.py +0 -106
  260. ledger/tests/testdata/generate_corporationaudit.py +0 -74
  261. ledger/tests/testdata/generate_events.py +0 -31
  262. ledger/tests/testdata/generate_miningledger.py +0 -13
  263. ledger/tests/testdata/generate_planets.py +0 -48
  264. ledger/tests/testdata/generate_walletjournal.py +0 -42
  265. ledger/tests/testdata/json/czarno-pins.json +0 -240
  266. ledger/tests/testdata/json/czarno-routes.json +0 -165
  267. ledger/tests/testdata/json/pins2.json +0 -538
  268. {aa_ledger-1.0.3.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
@@ -4,7 +4,9 @@ Character Audit Model
4
4
 
5
5
  # Django
6
6
  from django.core.cache import cache
7
+ from django.core.exceptions import ObjectDoesNotExist
7
8
  from django.db import models
9
+ from django.utils.functional import cached_property
8
10
  from django.utils.translation import gettext_lazy as _
9
11
 
10
12
  # Alliance Auth
@@ -12,7 +14,6 @@ from allianceauth.eveonline.models import EveCharacter, Token
12
14
  from allianceauth.services.hooks import get_extension_logger
13
15
 
14
16
  # Alliance Auth (External Libs)
15
- from app_utils.logging import LoggerAddTag
16
17
  from eveuniverse.models import EveMarketPrice, EveSolarSystem, EveType
17
18
 
18
19
  # AA Ledger
@@ -22,39 +23,38 @@ from ledger.app_settings import (
22
23
  LEDGER_USE_COMPRESSED,
23
24
  )
24
25
  from ledger.errors import TokenDoesNotExist
26
+ from ledger.helpers.eveonline import get_character_portrait_url
25
27
  from ledger.managers.character_audit_manager import (
26
28
  CharacterAuditManager,
27
29
  )
28
30
  from ledger.managers.character_journal_manager import CharWalletManager
29
31
  from ledger.managers.character_mining_manager import CharacterMiningLedgerEntryManager
30
32
  from ledger.models.general import (
31
- AuditBase,
32
- EveEntity,
33
33
  UpdateSectionResult,
34
+ UpdateStatusBaseModel,
35
+ WalletJournalEntry,
36
+ )
37
+ from ledger.models.helpers.update_manager import (
38
+ CharacterUpdateSection,
39
+ UpdateManager,
34
40
  UpdateStatus,
35
41
  )
42
+ from ledger.providers import AppLogger
36
43
 
37
- logger = LoggerAddTag(get_extension_logger(__name__), __title__)
44
+ logger = AppLogger(get_extension_logger(__name__), __title__)
38
45
 
39
46
 
40
- class CharacterAudit(AuditBase):
47
+ class CharacterOwner(models.Model):
41
48
  """A model to store character information."""
42
49
 
43
- class UpdateSection(models.TextChoices):
44
- WALLET_JOURNAL = "wallet_journal", _("Wallet Journal")
45
- MINING_LEDGER = "mining_ledger", _("Mining Ledger")
46
- PLANETS = "planets", _("Planets")
47
- PLANETS_DETAILS = "planets_details", _("Planets Details")
48
-
49
- @classmethod
50
- def get_sections(cls) -> list[str]:
51
- """Return list of section values."""
52
- return [choice.value for choice in cls]
50
+ objects: CharacterAuditManager = CharacterAuditManager()
53
51
 
54
- @property
55
- def method_name(self) -> str:
56
- """Return method name for this section."""
57
- return f"update_{self.value}"
52
+ class Meta:
53
+ default_permissions = ()
54
+ permissions = (
55
+ ("char_audit_manager", "Has access to all characters for own Corp"),
56
+ ("char_audit_admin_manager", "Has access to all characters"),
57
+ )
58
58
 
59
59
  id = models.AutoField(primary_key=True)
60
60
 
@@ -70,21 +70,12 @@ class CharacterAudit(AuditBase):
70
70
  max_digits=20, decimal_places=2, null=True, default=None
71
71
  )
72
72
 
73
- objects = CharacterAuditManager()
74
-
75
73
  def __str__(self) -> str:
76
74
  try:
77
75
  return f"{self.eve_character.character_name} ({self.id})"
78
76
  except AttributeError:
79
77
  return f"{self.character_name} ({self.id})"
80
78
 
81
- class Meta:
82
- default_permissions = ()
83
- permissions = (
84
- ("char_audit_manager", "Has access to all characters for own Corp"),
85
- ("char_audit_admin_manager", "Has access to all characters"),
86
- )
87
-
88
79
  @classmethod
89
80
  def get_esi_scopes(cls) -> list[str]:
90
81
  """Return list of required ESI scopes to fetch."""
@@ -99,24 +90,54 @@ class CharacterAudit(AuditBase):
99
90
  ]
100
91
 
101
92
  @property
102
- def get_status(self) -> UpdateStatus:
93
+ def get_status(self) -> UpdateStatusBaseModel:
103
94
  """Get the status of this character."""
104
95
  if self.active is False:
105
- return self.UpdateStatus.DISABLED
96
+ return UpdateStatus.DISABLED
106
97
 
107
- qs = CharacterAudit.objects.filter(pk=self.pk).annotate_total_update_status()
98
+ qs = CharacterOwner.objects.filter(pk=self.pk).annotate_total_update_status()
108
99
  total_update_status = list(qs.values_list("total_update_status", flat=True))[0]
109
- return self.UpdateStatus(total_update_status)
100
+ return UpdateStatus(total_update_status)
101
+
102
+ @cached_property
103
+ def alt_ids(self) -> models.QuerySet[EveCharacter]:
104
+ """Get all alt IDs for this Owner."""
105
+ alt_ids = (
106
+ EveCharacter.objects.filter(
107
+ character_ownership__user=self.eve_character.character_ownership.user
108
+ )
109
+ .order_by("character_id")
110
+ .values_list("character_id", flat=True)
111
+ )
112
+ return alt_ids
113
+
114
+ @cached_property
115
+ def is_orphan(self) -> bool:
116
+ """
117
+ Return True if this character is an orphan else False.
118
+
119
+ An orphan is a character that is not owned anymore by a user.
120
+ """
121
+ return self.character_ownership is None
122
+
123
+ @cached_property
124
+ def character_ownership(self) -> bool:
125
+ """
126
+ Return the character ownership object of this character.
127
+ """
128
+ try:
129
+ return self.eve_character.character_ownership
130
+ except ObjectDoesNotExist:
131
+ return None
110
132
 
111
133
  @property
112
- def alts(self) -> models.QuerySet[EveCharacter]:
113
- """Get all alts for this character."""
114
- alts = EveCharacter.objects.filter(
115
- character_ownership__user=self.eve_character.character_ownership.user
116
- ).select_related(
117
- "character_ownership",
134
+ def update_manager(self):
135
+ """Return the Update Manager helper for this owner."""
136
+ return UpdateManager(
137
+ owner=self,
138
+ update_section=CharacterUpdateSection,
139
+ update_status=CharacterUpdateStatus,
118
140
  )
119
- return alts
120
141
 
121
142
  @property
122
143
  def mining_ledger(self):
@@ -132,8 +153,30 @@ class CharacterAudit(AuditBase):
132
153
  def update_status(self):
133
154
  return self.ledger_update_status
134
155
 
156
+ def get_portrait(self, size: int = 64, as_html: bool = False) -> str:
157
+ """
158
+ Get the character portrait URL.
159
+
160
+ Args:
161
+ size (int, optional): The size of the portrait.
162
+ as_html (bool, optional): Whether to return the portrait as an HTML img tag.
163
+ Returns:
164
+ str: The URL of the character portrait or an HTML img tag.
165
+ """
166
+ return get_character_portrait_url(
167
+ character_id=self.eve_character.character_id,
168
+ size=size,
169
+ character_name=self.eve_character.character_name,
170
+ as_html=as_html,
171
+ )
172
+
135
173
  def get_token(self, scopes=None) -> Token:
136
174
  """Get the token for this character."""
175
+ if self.is_orphan: # pylint: disable=using-constant-test
176
+ raise TokenDoesNotExist(
177
+ f"Character {self} is an orphan and has no token."
178
+ ) from None
179
+
137
180
  token = (
138
181
  Token.objects.filter(character_id=self.eve_character.character_id)
139
182
  .require_scopes(scopes if scopes else self.get_esi_scopes())
@@ -167,59 +210,12 @@ class CharacterAudit(AuditBase):
167
210
  )
168
211
 
169
212
 
170
- class WalletJournalEntry(models.Model):
171
- amount = models.DecimalField(
172
- max_digits=20, decimal_places=2, null=True, default=None
173
- )
174
- balance = models.DecimalField(
175
- max_digits=20, decimal_places=2, null=True, default=None
176
- )
177
- context_id = models.BigIntegerField(null=True, default=None)
178
-
179
- class ContextType(models.TextChoices):
180
- STRUCTURE_ID = "structure_id"
181
- STATION_ID = "station_id"
182
- MARKET_TRANSACTION_ID = "market_transaction_id"
183
- CHARACTER_ID = "character_id"
184
- CORPORATION_ID = "corporation_id"
185
- ALLIANCE_ID = "alliance_id"
186
- EVE_SYSTEM = "eve_system"
187
- INDUSTRY_JOB_ID = "industry_job_id"
188
- CONTRACT_ID = "contract_id"
189
- PLANET_ID = "planet_id"
190
- SYSTEM_ID = "system_id"
191
- TYPE_ID = "type_id"
192
-
193
- context_id_type = models.CharField(
194
- max_length=30, choices=ContextType.choices, null=True, default=None
195
- )
196
- date = models.DateTimeField()
197
- description = models.CharField(max_length=500)
198
- first_party = models.ForeignKey(
199
- EveEntity,
200
- on_delete=models.SET_DEFAULT,
201
- default=None,
202
- null=True,
203
- blank=True,
204
- related_name="+",
205
- )
206
- entry_id = models.BigIntegerField()
207
- reason = models.CharField(max_length=500, null=True, default=None)
208
- ref_type = models.CharField(max_length=72)
209
- second_party = models.ForeignKey(
210
- EveEntity,
211
- on_delete=models.SET_DEFAULT,
212
- default=None,
213
- null=True,
214
- blank=True,
215
- related_name="+",
216
- )
217
- tax = models.DecimalField(max_digits=20, decimal_places=2, null=True, default=None)
218
- tax_receiver_id = models.IntegerField(null=True, default=None)
213
+ class CharacterWalletJournalEntry(WalletJournalEntry):
214
+ objects: CharWalletManager = CharWalletManager()
219
215
 
220
216
  class Meta:
221
- abstract = True
222
217
  indexes = (
218
+ models.Index(fields=["character"]),
223
219
  models.Index(fields=["date"]),
224
220
  models.Index(fields=["amount"]),
225
221
  models.Index(fields=["entry_id"]),
@@ -229,32 +225,30 @@ class WalletJournalEntry(models.Model):
229
225
  )
230
226
  default_permissions = ()
231
227
 
232
-
233
- class CharacterWalletJournalEntry(WalletJournalEntry):
234
228
  character = models.ForeignKey(
235
- CharacterAudit,
229
+ CharacterOwner,
236
230
  on_delete=models.CASCADE,
237
231
  related_name="ledger_character_journal",
238
232
  )
239
233
 
240
- objects = CharWalletManager()
241
-
242
234
  def __str__(self):
243
- return f"Character Wallet Journal: RefType: {self.ref_type} - {self.first_party.name} -> {self.second_party.name}: {self.amount} ISK"
235
+ return f"Character Wallet Journal: RefType: {self.ref_type} - {self.first_party} -> {self.second_party}: {self.amount} ISK"
244
236
 
245
237
  @classmethod
246
238
  def get_visible(cls, user):
247
- chars_vis = CharacterAudit.objects.visible_to(user)
239
+ chars_vis = CharacterOwner.objects.visible_to(user)
248
240
  return cls.objects.filter(character__in=chars_vis)
249
241
 
250
242
 
251
- # Mining Models
243
+ class CharacterMiningLedger(models.Model):
244
+ objects: CharacterMiningLedgerEntryManager = CharacterMiningLedgerEntryManager()
252
245
 
246
+ class Meta:
247
+ default_permissions = ()
253
248
 
254
- class CharacterMiningLedger(models.Model):
255
249
  id = models.CharField(max_length=50, primary_key=True)
256
250
  character = models.ForeignKey(
257
- CharacterAudit, on_delete=models.CASCADE, related_name="ledger_character_mining"
251
+ CharacterOwner, on_delete=models.CASCADE, related_name="ledger_character_mining"
258
252
  )
259
253
  date = models.DateTimeField()
260
254
  type = models.ForeignKey(
@@ -298,24 +292,22 @@ class CharacterMiningLedger(models.Model):
298
292
  price = None
299
293
  return price
300
294
 
301
- objects = CharacterMiningLedgerEntryManager()
302
-
303
- class Meta:
304
- default_permissions = ()
305
-
306
295
  def __str__(self) -> str:
307
296
  return f"{self.character} {self.id}"
308
297
 
309
298
 
310
- class CharacterUpdateStatus(UpdateStatus):
299
+ class CharacterUpdateStatus(UpdateStatusBaseModel):
311
300
  """A Model to track the status of the last update."""
312
301
 
313
- character = models.ForeignKey(
314
- CharacterAudit, on_delete=models.CASCADE, related_name="ledger_update_status"
302
+ owner = models.ForeignKey(
303
+ CharacterOwner, on_delete=models.CASCADE, related_name="ledger_update_status"
315
304
  )
316
305
  section = models.CharField(
317
- max_length=32, choices=CharacterAudit.UpdateSection.choices, db_index=True
306
+ max_length=32, choices=CharacterUpdateSection.choices, db_index=True
318
307
  )
319
308
 
320
309
  def __str__(self) -> str:
321
- return f"{self.character} - {self.section} - {self.is_success}"
310
+ return f"{self.owner} - {self.section}"
311
+
312
+ class Meta:
313
+ default_permissions = ()
@@ -4,19 +4,19 @@ Corporation Audit Model
4
4
 
5
5
  # Django
6
6
  from django.db import models
7
+ from django.utils.functional import cached_property
7
8
  from django.utils.translation import gettext_lazy as _
8
9
 
9
10
  # Alliance Auth
11
+ from allianceauth.authentication.models import UserProfile
10
12
  from allianceauth.eveonline.models import EveCharacter, EveCorporationInfo
11
13
  from allianceauth.services.hooks import get_extension_logger
12
14
  from esi.errors import TokenError
13
15
  from esi.models import Token
14
16
 
15
- # Alliance Auth (External Libs)
16
- from app_utils.logging import LoggerAddTag
17
-
18
17
  # AA Ledger
19
18
  from ledger import __title__
19
+ from ledger.helpers.eveonline import get_corporation_logo_url
20
20
  from ledger.managers.corporation_audit_manager import CorporationAuditManager
21
21
  from ledger.managers.corporation_journal_manager import (
22
22
  CorporationDivisionManager,
@@ -24,56 +24,45 @@ from ledger.managers.corporation_journal_manager import (
24
24
  )
25
25
  from ledger.models.characteraudit import WalletJournalEntry
26
26
  from ledger.models.general import (
27
- AuditBase,
27
+ UpdateStatusBaseModel,
28
+ )
29
+ from ledger.models.helpers.update_manager import (
30
+ CorporationUpdateSection,
31
+ UpdateManager,
28
32
  UpdateStatus,
29
33
  )
30
- from ledger.providers import esi
34
+ from ledger.providers import AppLogger, esi
31
35
 
32
- logger = LoggerAddTag(get_extension_logger(__name__), __title__)
36
+ logger = AppLogger(get_extension_logger(__name__), __title__)
33
37
 
34
38
 
35
- class CorporationAudit(AuditBase):
39
+ class CorporationOwner(models.Model):
36
40
  """A model to store corporation information."""
37
41
 
38
- class UpdateSection(models.TextChoices):
39
- WALLET_DIVISION_NAMES = "wallet_division_names", _("Divisions Names")
40
- WALLET_DIVISION = "wallet_division", _("Divisions")
41
- WALLET_JOURNAL = "wallet_journal", _("Wallet Journal")
42
-
43
- @classmethod
44
- def get_sections(cls) -> list[str]:
45
- """Return list of section values."""
46
- return [choice.value for choice in cls]
42
+ class Meta:
43
+ default_permissions = ()
44
+ permissions = (
45
+ ("corp_audit_manager", "Has Access to own Corporations."),
46
+ ("corp_audit_admin_manager", "Has access to all Corporations."),
47
+ )
47
48
 
48
- @property
49
- def method_name(self) -> str:
50
- """Return method name for this section."""
51
- return f"update_{self.value}"
49
+ objects: CorporationAuditManager = CorporationAuditManager()
52
50
 
53
51
  corporation_name = models.CharField(max_length=100, null=True, default=None)
54
52
 
55
53
  active = models.BooleanField(default=True)
56
54
 
57
- corporation = models.OneToOneField(
55
+ eve_corporation = models.OneToOneField(
58
56
  EveCorporationInfo,
59
57
  on_delete=models.CASCADE,
60
58
  related_name="ledger_corporationaudit",
61
59
  )
62
60
 
63
- objects = CorporationAuditManager()
64
-
65
61
  def __str__(self) -> str:
66
62
  try:
67
- return f"{self.corporation.corporation_name} ({self.id})"
63
+ return f"{self.eve_corporation.corporation_name} ({self.id})"
68
64
  except AttributeError:
69
- return f"{self.corporation} ({self.id})"
70
-
71
- class Meta:
72
- default_permissions = ()
73
- permissions = (
74
- ("corp_audit_manager", "Has Access to own Corporations."),
75
- ("corp_audit_admin_manager", "Has access to all Corporations."),
76
- )
65
+ return f"{self.eve_corporation} ({self.id})"
77
66
 
78
67
  @classmethod
79
68
  def get_esi_scopes(cls) -> list[str]:
@@ -93,14 +82,14 @@ class CorporationAudit(AuditBase):
93
82
  ]
94
83
 
95
84
  @property
96
- def get_status(self) -> UpdateStatus:
85
+ def get_status(self) -> UpdateStatusBaseModel:
97
86
  """Get the status of this corporation."""
98
87
  if self.active is False:
99
- return self.UpdateStatus.DISABLED
88
+ return UpdateStatus.DISABLED
100
89
 
101
- qs = CorporationAudit.objects.filter(pk=self.pk).annotate_total_update_status()
90
+ qs = CorporationOwner.objects.filter(pk=self.pk).annotate_total_update_status()
102
91
  total_update_status = list(qs.values_list("total_update_status", flat=True))[0]
103
- return self.UpdateStatus(total_update_status)
92
+ return UpdateStatus(total_update_status)
104
93
 
105
94
  @property
106
95
  def update_status(self):
@@ -112,7 +101,7 @@ class CorporationAudit(AuditBase):
112
101
  scopes.append("esi-characters.read_corporation_roles.v1")
113
102
 
114
103
  char_ids = EveCharacter.objects.filter(
115
- corporation_id=self.corporation.corporation_id
104
+ corporation_id=self.eve_corporation.corporation_id
116
105
  ).values("character_id")
117
106
 
118
107
  tokens = Token.objects.filter(character_id__in=char_ids).require_scopes(scopes)
@@ -138,6 +127,48 @@ class CorporationAudit(AuditBase):
138
127
  )
139
128
  return False
140
129
 
130
+ @cached_property
131
+ def corp_members_ids(self):
132
+ """Return the member ids for this corporation."""
133
+ return EveCharacter.objects.filter(
134
+ corporation_id=self.eve_corporation.corporation_id
135
+ ).values_list("character_id", flat=True)
136
+
137
+ @cached_property
138
+ def auth_accounts(self):
139
+ """Return the user profiles for this corporation."""
140
+ return UserProfile.objects.filter(
141
+ main_character__isnull=False,
142
+ ).order_by(
143
+ "user__profile__main_character__character_name",
144
+ )
145
+
146
+ @property
147
+ def update_manager(self):
148
+ """Return the Update Manager helper for this corporation."""
149
+ return UpdateManager(
150
+ owner=self,
151
+ update_section=CorporationUpdateSection,
152
+ update_status=CorporationUpdateStatus,
153
+ )
154
+
155
+ def get_portrait(self, size: int = 64, as_html: bool = False) -> str:
156
+ """
157
+ Get the corporation portrait URL.
158
+
159
+ Args:
160
+ size (int, optional): The size of the portrait.
161
+ as_html (bool, optional): Whether to return the portrait as an HTML img tag.
162
+ Returns:
163
+ str: The URL of the character portrait or an HTML img tag.
164
+ """
165
+ return get_corporation_logo_url(
166
+ corporation_id=self.eve_corporation.corporation_id,
167
+ size=size,
168
+ corporation_name=self.eve_corporation.corporation_name,
169
+ as_html=as_html,
170
+ )
171
+
141
172
  def update_wallet_division_names(self, force_refresh: bool) -> None:
142
173
  return self.ledger_corporation_division.update_or_create_esi_names(
143
174
  self, force_refresh=force_refresh
@@ -155,10 +186,13 @@ class CorporationAudit(AuditBase):
155
186
 
156
187
 
157
188
  class CorporationWalletDivision(models.Model):
158
- objects = CorporationDivisionManager()
189
+ objects: CorporationDivisionManager = CorporationDivisionManager()
190
+
191
+ class Meta:
192
+ default_permissions = ()
159
193
 
160
194
  corporation = models.ForeignKey(
161
- CorporationAudit,
195
+ CorporationOwner,
162
196
  on_delete=models.CASCADE,
163
197
  related_name="ledger_corporation_division",
164
198
  )
@@ -166,39 +200,50 @@ class CorporationWalletDivision(models.Model):
166
200
  balance = models.DecimalField(max_digits=20, decimal_places=2)
167
201
  division_id = models.IntegerField()
168
202
 
203
+
204
+ class CorporationWalletJournalEntry(WalletJournalEntry):
205
+
206
+ objects: CorporationWalletManager = CorporationWalletManager()
207
+
208
+ # pylint: disable=duplicate-code
169
209
  class Meta:
210
+ indexes = (
211
+ models.Index(fields=["division"]),
212
+ models.Index(fields=["date"]),
213
+ models.Index(fields=["amount"]),
214
+ models.Index(fields=["entry_id"]),
215
+ models.Index(fields=["ref_type"]),
216
+ models.Index(fields=["first_party"]),
217
+ models.Index(fields=["second_party"]),
218
+ )
170
219
  default_permissions = ()
171
220
 
172
-
173
- class CorporationWalletJournalEntry(WalletJournalEntry):
174
221
  division = models.ForeignKey(
175
222
  CorporationWalletDivision,
176
223
  on_delete=models.CASCADE,
177
224
  related_name="ledger_corporation_journal",
178
225
  )
179
226
 
180
- objects = CorporationWalletManager()
181
-
182
227
  def __str__(self):
183
228
  return f"Corporation Wallet Journal: RefType: {self.ref_type} - {self.first_party.name} -> {self.second_party.name}: {self.amount} ISK"
184
229
 
185
230
  @classmethod
186
231
  def get_visible(cls, user):
187
- corps_vis = CorporationAudit.objects.visible_to(user)
232
+ corps_vis = CorporationOwner.objects.visible_to(user)
188
233
  return cls.objects.filter(division__corporation__in=corps_vis)
189
234
 
190
235
 
191
- class CorporationUpdateStatus(UpdateStatus):
236
+ class CorporationUpdateStatus(UpdateStatusBaseModel):
192
237
  """A Model to track the status of the last update."""
193
238
 
194
- corporation = models.ForeignKey(
195
- CorporationAudit,
239
+ owner = models.ForeignKey(
240
+ CorporationOwner,
196
241
  on_delete=models.CASCADE,
197
242
  related_name="ledger_corporation_update_status",
198
243
  )
199
244
  section = models.CharField(
200
- max_length=32, choices=CorporationAudit.UpdateSection.choices, db_index=True
245
+ max_length=32, choices=CorporationUpdateSection.choices, db_index=True
201
246
  )
202
247
 
203
248
  def __str__(self) -> str:
204
- return f"{self.corporation} - {self.section} - {self.is_success}"
249
+ return f"{self.owner} - {self.section} - {self.is_success}"